0

当我测试双指针行为时,我得到了一个我不太理解的结果。

==> 代码 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#

似乎 printf 从第 n 个单词(1 和 9)显示我们如何解释指针的这种行为?

4

4 回答 4

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”

但是你真的应该忘记这一点,因为它永远不会有用!这是未定义的行为,不应使用。

于 2013-07-12T14:26:21.627 回答
1

char **argv是指向 a 的指针char *(有时更简单地称为字符串)。当你这样做时,你取消引用这个指针*argv。此取消引用的结果是 a char *,或者换句话说,它是 a 的地址char。当您对结果进行加法时,您的代码正在计算一个新地址。因此,例如 while*argv将是字符串中第一个字符*argv+1的地址,是字符串中第二个字符的地址。

当您添加一个比字符串长度更长的数字时,您将退出“安全”。请记住,C 将允许您进行指针运算,使您越过字符串的末尾。在您的第二个示例中,您要求 printf 从开头开始 9 个字节*argv并从那里打印字符到下一个\0(或 NULL)字节。您正在有效地从程序的进程空间中读取任意内存,这解释了正在打印的内容。

于 2013-07-12T14:35:41.860 回答
1

其实问题不止一个。

  1. 拜托,拜托,不要以root身份工作。只是不要。
  2. 您的语法 ( *argv + 9) 字面意思是:“defeference argv 并移动指针 9 个字符”,实际上,如果您将 9 个字符从./geip 1255您移动到55​​. 因此,要么使用argv[i](i = 1..N表示参数索引),要么如果你想用困难的方式来做,你必须添加括号:*(argv + i)
  3. 尝试更好地格式化您的代码 - 它不仅对 stackoverflow 人员而且对您来说都更具可读性。

例如,当您运行时./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 将 bw 5(见评论)
  • argv[>5]这不是一个好主意,因为没有更多的论点。所以你最好检查argc一下有多少参数。
于 2013-07-12T14:35:54.920 回答
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 个字节。

于 2013-07-12T14:36:38.397 回答