【问题标题】:Pointer to array of pointers returns to initial address指向指针数组的指针返回初始地址
【发布时间】:2016-04-23 05:26:57
【问题描述】:

我正在研究这个创建 shell 的小程序。 parse() 接受一个字符指针line 和一个字符指针数组argv,将每个字的地址保存在argv 中。

void  parse(char *line, char **argv) {
 while (*line != '\0') {       /* if not the end of line ....... */
      while (*line == ' ' || *line == '\t' || *line == '\n')
           *line++ = '\0';     /* replace white spaces with 0    */
      *argv++ = line;          /* save the argument position     */
      printf("%p\n",*argv);
      while (*line != '\0' && *line != ' ' &&
             *line != '\t' && *line != '\n')
           line++;             /* skip the argument until ...    */
 }
 *argv = '\0';                 /* mark the end of argument list  */
}

我不明白的是,argv 在函数退出后以某种方式回到了第一个单词。主要函数调用:

parse(line, argv);       /*   parse the line               */
      if (strcmp(argv[0], "exit") == 0)  /* is it an "exit"?     */
           exit(0);

argv[0]line 的开头,而之前在line 的结尾呢?

【问题讨论】:

  • *argv = '\0'; ,argv是指向字符串的指针不是字符串,你的意思是*argv = NULL吗?
  • 这个问题与stackoverflow.com/q/25769443/694576 相关,如果不是与后者重复的话。
  • @AlterMann 可能,尽管 OP 代码确实有效,因为 '\0'0 相同(即 int 的值为零)
  • @M.M,是的,NULL 和 0 在这种情况下是可以互换的。

标签: c arrays pointers parameter-passing


【解决方案1】:

原因是C中参数是按值传递的。这样想:

void func(int a)
{
     a = 20;
}

int main()
{
     int val = 10;
     printf("%d", val);
     func(val);
     printf("%d", val);
}

在上面的两个打印中,打印出来的值都是 10。如果你想修改 func 中的 val,那么你必须传递它的地址。指针也是如此。指针是按值传递的,就像任何其他参数一样。因此,如果你有这样的事情:

#include <stdio.h>

void func(char **argv)
{
  while (*argv != 0) {
    printf("%s\n", *argv);
    argv++;
  } 
  printf("*****done*****\n");
}

int main(int argc, char **argv)
{
  func(argv);
  printf("%s\n", argv[0]);
}

然后你运行它:

gcc a.c
./a.out hello how are you

输出将是:

./a.out
hello
how
are
you
*****done*****
./a.out

如果你想让 argv 从函数返回时指向最后一个参数,那么你必须传递它的地址:

#include <stdio.h>

void func(char ***argv)
{
  while (**argv != 0) {
    printf("%s\n", **argv);
    (*argv)++;
  } 
  (*argv)--;
  printf("*****done*****\n");
}

int main(int argc, char **argv)
{
  func(&argv);
  printf("%s\n", argv[0]);
}

现在输出将是:

./a.out
hello
how
are
you
*****done*****
you

【讨论】:

    【解决方案2】:

    如果我知道混淆在哪里,当您调用 void parse(char *line, char **argv)lineargv 指针发送到函数时,函数会接收每个指针的 COPY,每个副本都有一个自己的地址。

    因此,无论您在函数中对指针本身做什么(例如,通过argv++, argv++ 迭代argv,这些更改在main() 中永远不会出现,因为增量只发生在copy 和 main 中的 原始指针 对此一无所知。

    现在,如果您更改 argv 中任何单个字符串的内容,这些更改将在 main 中看到,但任何其他非内容修改更改仅适用于您的函数。

    在函数中更改指针的唯一方法是将指针的地址传递给函数。这会给你一个void parse(char **line, char ***argv) 的原型然后你可以在你的函数中更改指针本身并让这些更改在main 中可见(例如char *tmp = (*argv)[0]; (*argv)[0] = (*argv)[1]; (*argv)[1] = tmp;

    【讨论】:

      猜你喜欢
      • 2010-10-11
      • 1970-01-01
      • 2015-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多