Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指向指针数组的指针返回初始地址_C_Arrays_Pointers_Parameter Passing - Fatal编程技术网

C 指向指针数组的指针返回初始地址

C 指向指针数组的指针返回初始地址,c,arrays,pointers,parameter-passing,C,Arrays,Pointers,Parameter Passing,我在看这个创建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++ =

我在看这个创建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]
在前面的
行的末尾时,在
行的开头是怎样的?

原因是参数是通过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]);
}
产出将是:

./a.out
hello
how
are
you
*****done*****
./a.out
./a.out
hello
how
are
you
*****done*****
you
如果希望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]);
}

原因是参数是通过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]);
}
产出将是:

./a.out
hello
how
are
you
*****done*****
./a.out
./a.out
hello
how
are
you
*****done*****
you
如果希望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]);
}

如果我理解混淆的地方,当调用
void parse(char*line,char**argv)
向函数发送
line
argv
指针时,函数接收每个指针的副本,每个副本都有自己的地址

因此,无论您对函数中的指针本身做了什么(例如,通过
argv++,argv++
迭代
argv
),这些更改在
main()中都不会看到
因为增量只发生在参数向量的副本上,而
main
中的原始指针对此没有任何线索

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


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

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

因此,无论您对函数中的指针本身做了什么(例如,通过
argv++,argv++
迭代
argv
),这些更改在
main()中都不会看到
因为增量只发生在参数向量的副本上,而
main
中的原始指针对此没有任何线索

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


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

*argv='\0';
argv
是指向字符串的指针,而不是字符串,你的意思是说
*argv=NULL
?请参阅。这个问题与后者相关,如果不是后者的副本。@AlterMann可能,尽管OP代码确实有效,因为
'\0'
0
相同(即值为零的
int
)@M.M,是的,
NULL
和0在此上下文中是可互换的。
*argv='\0';
argv
是指向字符串的指针,而不是字符串,你的意思是
*argv=NULL
?请参见。这个问题与后者相关,如果不是后者的副本。@AlterMann可能,尽管操作代码确实有效,因为
'\0'
0
(即值为零的
int
)@M.M,是的,
NULL
和0在此上下文中是可互换的。