将char * vs char **作为参数传递给C中的函数

时间:2010-11-22 06:37:00

标签: c char parameter-passing

我已经阅读了几篇关于在C中传递char *的讨论。

stackoverflow: passing-an-array-of-strings-as-parameter-to-a-function-in-c
stackoverflow: how-does-an-array-of-pointers-to-pointers-work
stackoverflow: whats-your-favorite-programmer-ignorance-pet-peeve
drexel.edu: Character arrays

其中许多都包括阵列的讨论,但我想远离那个。

我正在编写一个示例程序来教我自己在C中传递char *char **。这是传递char *而不使用(指向)数组的练习。也无需担心执行效率。 : - )

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void get_args_works(int, char **, char **);
void get_args_broken(int, char **, char *);
char *get_string(int, char **);

int main(int argc, char **argv)
{
  char *string_works;
  char *string_broken;

  get_args_works(argc, argv, &string_works);
  get_args_broken(argc, argv, string_broken);

  printf("in main string_works (%p) = %s\n",string_works,string_works);
  free(string_works);

  printf("in main string_broken (%p) = %s\n",string_broken,string_broken);
  free(string_broken);
}

void get_args_works(int argc, char **argv, char **string)
{
    *string = get_string(argc, argv);
    printf("in get_args_works %p string %s\n",*string,*string);
}

void get_args_broken(int argc, char **argv, char *string)
{
  string = get_string(argc, argv);
  printf("in get_args_broken %p string %s\n",string,string);
}

char * get_string(int argc, char **argv)
{
  int i;
  char *string;
  string = malloc(40);

  // placeholder in case -s switch not found below
  strcpy(string,"-s switch not found below");

  for(i = 0; i < argc; i++)
    {
      if(argv[i][0] == '-')
        {
          switch(argv[i][1])
            {
            case 's':
              // release above malloc(40) for "-s switch not found below"
              free(string);
              // make room for storing variable
              string = malloc(strlen(argv[++i]) + 1);
              // the argv just after -s
              strcpy (string,argv[i]);
              break;
            }
        }
    }
  return string;
}

您还可以查看same code on github

上面的代码有点自我记录。 main()声明了两个char *变量,并将它们作为参数传递给各自的get_args()函数。

每个get_args()函数调用char * get_string(int, char **),使用完全相同的调用(但收集返回值的方式不同)。

get_string()工作正常;它执行malloc()并将指针返回给调用函数。该代码有效,每个get_args()函数都会收到我期望的返回值。

但是,当get_args()函数返回main()时,为什么解除引用的指针值会返回main(来自get_args_works(),而不是指针的值(来自get_args_broken() )?

(即我可以看到,如果我在作为参数发送时取消引用指针(&string_works),它就可以工作。但是为什么?char * string_broken是不是已经指针?为什么它需要作为参数发送时,“额外”取消引用?)

我希望得到一个成功的答案,解释你是如何(是的,你)概念化将char *作为参数发送而不是接收它作为函数的返回值。

2 个答案:

答案 0 :(得分:4)

int get_args_broken(int argc, char **argv, char *string)
{
  string = get_string(argc, argv);
  printf("in get_args_broken %p string %s\n",string,string);
}

您只修改string本地(自动)变量。调用者无法以任何方式看到这一点。请注意,这意味着您正在释放main中的野生指针。

出于同样的原因,这是错误的:

int get_sum(int sum, int a, int b)
{
  sum = a + b;
}

是;该参数按值复制。另外,你没有返回int(正如你声明的那样)。

int get_args_works(int argc, char **argv, char **string)
{
    *string = get_string(argc, argv);
    printf("in get_args_works %p string %s\n",*string,*string);
}

是正确的(除了缺失的回报)。你没有修改string,这是没有意义的。您正在{/ 1}}中修改对象 的位置,在本例中为string

编辑:如果有一个函数调用main,你需要三倍* argv,并且你想将该函数的变量设置为另一个char **。 E.G。

char *

答案 1 :(得分:1)

将指针用于指针(此处为get_args_works())的一个需求是修改(或返回)多于函数的变量,就像在C中一样,它不可能返回多个变量。

get_args_works()工作'因为,你正在将指针传递给指针&amp;在main()。{/ p>中有对它的引用

但是在get_args_broken()中,你只传递一个指针。这里没有错,现在你做malloc()&amp;将内存分配的字符串返回给get_args_broken(),这里仍然没有错。但是现在,这个mem分配的字符串是本地&amp; main()没有对此var的引用。因此,当您在main()中取消引用char *string_broken;时,它可能会导致未定义的行为。

希望这很清楚。