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

Thu*_*bit 9 c char parameter-passing

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

计算器:使-AN-阵列的串-作为参数到一个函数式-C
计算器:如何-不-AN-阵列的指针到指针工作
计算器:最新-你的- favorite-programmer-ignorance-pet-
peeve drexel.edu:字符数组

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

我正在写一个示例程序来教自己有关的传球char *,并char **在C.这是在传递的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;
}
Run Code Online (Sandbox Code Playgroud)

您还可以在github上查看相同的代码

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

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

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

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

(即我可以看到,如果我取指针(&string_works)作为参数发送时,它的工作原理.但是,为什么?是不是char * string_broken已经是一个指针?为什么作为一个参数发送时,它需要"额外"解引用?)

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

Mat*_*hen 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);
}
Run Code Online (Sandbox Code Playgroud)

您只是修改string本地(自动)变量。这对于调用者来说是不可见的。请注意,这意味着您正在释放 main 中的野指针。

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

int get_sum(int sum, int a, int b)
{
  sum = a + b;
}
Run Code Online (Sandbox Code Playgroud)

是; 参数按值复制。另外,您没有返回 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);
}
Run Code Online (Sandbox Code Playgroud)

是正确的(除了缺少返回)。您没有修改string,这毫无意义。您正在修改中位置的对象string,在本例中是一个char *.

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

void trip_main(int *argc, char ***argv)
{
  *argc = 10; 
  *argv = malloc(*argc * sizeof(char *));
}

void caller()
{
  char **argv;
  int argc;
  trip_main(&argc, &argv);
}
Run Code Online (Sandbox Code Playgroud)

  • @ThunderRabbit:是时候学习如何从编译器中打开更多警告,或者获得更好的编译器了。如果您的编译器没有抱怨声明为返回值的函数在没有返回值的情况下返回,那么它......好吧,没有完全破坏,但没有应有的帮助。编译器警告是你的朋友 - 听它说话,并确保它是冗长的。对于 GCC,一个好的起点是“-Wall”;我通常使用“-Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition”(最后一个是因为我处理过时的代码)。《白影》也不错啊…… (2认同)