当我测试双指针行为时,我得到了一个我不太了解的结果。
==>代码1:
int main (int argc , char **argv)
{
if(*argv+1 ==NULL)
{
printf("NULL pointer \n");
exit(0) ;
}
else
{
printf("test double pointer[] : %s \n ",*argv+1);
}
return(0);
}
====>结果1
root@root:/home/aa/test# ./geip 1255
test double pointer[] : /geip
root@root:/home/aa/test#
===>代码2:
int main (int argc , char **argv)
{
if(*argv+9 ==NULL)
{
printf("NULL pointer \n");
exit(0) ;
}
else
{
printf("test double pointer[] : %s \n ",*argv+9);
}
return(0);
}
==>结果2:
root@root:/home/aa/test# ./geip 1255
test double pointer[] : 55
root@root:/home/aa/test#
==>结果3:
root@root:/home/aa/test# ./geip
test double pointer[] : ELL=/bin/bash
root@root:/home/aa/test#
似乎是第n个字(1和9)的printf显示 我们如何解释指针的这种行为?
答案 0 :(得分:10)
你错了。
*argv+1
将被解释为(argv[0])+1
,因为argv[0]
为“./geip”,您将获得“/ geip”。
*argv+9
将被解释为(argv[0])+9
,但由于argv[0]
只有长度为6,因此结果未定义。
在您的情况下,argv可能存储为:
. / g e i p \0 1 2 5 5 \0
0 1 2 3 4 5 6 7 8 9 10 11
这解释了为什么+9
会让你“55”
但是你应该忘记它,因为它永远不会有用!这是未定义的行为,不应该被使用。
答案 1 :(得分:1)
char **argv
是指向char *
的指针(有时简称为字符串)。执行*argv
时取消引用此指针。此取消引用的结果是char *
,换句话说,它是char
的地址。当您对结果进行添加时,您的代码将计算新地址。因此,例如,当*argv
是字符串中第一个字符的地址时,*argv+1
是字符串中第二个字符的地址。
当您添加一个长度超过字符串长度的数字时,您将退出“安全”状态。请记住,C将允许您执行指针运算,使您超过字符串的结尾。在第二个示例中,您要求printf在*argv
的开头超过9个字节,并从那里打印字符到下一个\0
(或NULL)字节。您正在从程序的进程空间中有效地读取任意内存,这可以解释正在打印的内容。
答案 2 :(得分:1)
实际上存在多个问题。
*argv + 9
)的字面意思是:“defference argv并移动指针9个字符”,实际上,如果你从./geip 1255
移动9个字符,你将到达55
。因此,使用argv[i]
(i = 1..N
表示参数索引)或者如果您想要这么做,您必须添加括号:*(argv + i)
。例如,当您运行./geip a b c 123
:
argv[0]
string
持有程序名称 - ./geip
argv[1]
string
持有第一个参数 - a
argv[2]
string
持有第二个参数 - b
argv[3]
string
持有第三个参数 - c
argv[4]
string
持有第四个参数 - 123
argv[5]
为NULL,因为argc将会5
(见评论)argv[>5]
不是一个好主意,因为没有更多的论据。因此,您最好检查argc
以查看有多少参数。答案 3 :(得分:0)
你只是做一个指针算术: ** argv是指针列表的指针 * argv是列表的负责人
//char **argv is given from outthere
char *p;
p = *argv; // the same as "p = *argv[0]"
for (int i = 0; i < 100) {
printf("Next: %s\n", p+i);
}
尝试运行它并查看从列表头部到下一个100字节的内存转储。