C 指向指针数组的指针返回初始地址
我在看这个创建shell的小程序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++ =
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在此上下文中是可互换的。