【问题标题】:Passing char * vs char ** as parameters to a function in C将 char * vs char ** 作为参数传递给 C 中的函数
【发布时间】:2010-11-22 06:36:59
【问题描述】:

我已经阅读了几个关于在 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())?

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

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

【问题讨论】:

    标签: c char parameter-passing


    【解决方案1】:
    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,这毫无意义。您正在修改对象atstring 中的位置,在本例中为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);
    }
    

    【讨论】:

    • 嗯。我想这可能是理解它的一个很好的简单方法。它不以任何方式谈论 char * 。但是为什么我们不需要将 argv 增加三倍呢?嗯。
    • 天啊!!!我怎么会错过无效的返回类型? ?我一直在写这个问题...!!!!哦!!!!
    • @ThunderRabbit:是时候学习如何从编译器打开更多警告,或者获得更好的编译器了。如果您的编译器没有抱怨声明为返回值但不返回值的函数,那么它是......好吧,不是完全损坏,但没有应有的帮助。编译器警告是你的朋友——听它说话,并确保它是冗长的。对于 GCC,一个好的起点是“-Wall”;我通常使用'-Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition'(最后一个,因为我在处理过时的代码)。 “-Wshadow”也不错……
    • 谢谢,乔恩;我正在使用 gcc,所以我一定要检查 -W 选项。
    【解决方案2】:

    使用指向指针的指针(此处为 get_args_works())的需要之一是修改(或返回)比函数中的变量更多的内容,因为在 C 中不可能返回多个变量。

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

    希望这很清楚。

    【讨论】:

      猜你喜欢
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      • 2016-07-21
      • 2012-07-26
      • 1970-01-01
      相关资源
      最近更新 更多