代码之家  ›  专栏  ›  技术社区  ›  Thunder Rabbit Jonathan Delean

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

  •  9
  • Thunder Rabbit Jonathan Delean  · 技术社区  · 14 年前

    我读过几篇关于在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

    其中很多都包括数组的讨论,但我想远离它。

    我正在写一个示例程序来教自己 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() 功能。

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

    get_string() 工作很好;它可以 malloc() 并返回指向调用函数的指针。代码有效,而且每个 获取参数() 函数按预期接收返回值。

    但是,当get_args()函数返回到 主() ,为什么取消引用的指针值返回到main(从 get_args_works() ,但不是指针的值(从 get_args_broken() )?

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

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

    2 回复  |  直到 7 年前
        1
  •  4
  •   Matthew Flaschen    14 年前
    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);
    }
    

    是正确的(除了丢失的报税表)。你不是在修改 一串 ,这是毫无意义的。你正在修改对象 地点在 一串 ,在本例中是 char *

    编辑:如果有一个函数调用main,则需要将argv增加三倍,并且希望将该函数的变量设置为另一个char**。例如。

    void trip_main(int *argc, char ***argv)
    {
      *argc = 10; 
      *argv = malloc(*argc * sizeof(char *));
    }
    
    void caller()
    {
      char **argv;
      int argc;
      trip_main(&argc, &argv);
    }
    
        2
  •  1
  •   Srikar Appalaraju Tonetel    14 年前

    需要使用指向指针的指针之一(这里 get_args_works() )是从函数中修改(或返回)多个变量,如在C中,不可能返回多个变量。

    获取参数工作() 很好,因为您正在将指针传递给指针&在您的 main() .

    但是在 get_args_broken() 你只是在传递一个指针。这里没什么问题,现在你有了 malloc() &将内存分配字符串返回给 把参数弄坏() ,这里还是没什么问题。但现在,这个mem分配的字符串是local& 主() 没有对该变量的引用。因此当您取消引用 char *string_broken; 在main()中,它可能会导致未定义的行为。

    希望这是清楚的。