为什么不是连续数组条目的地址,也是连续的?

时间:2016-02-06 17:18:03

标签: c arrays pointers pointer-arithmetic

当我跑步时

char * a = "string";
char * b = a;
while (*a != '\0')
    printf("%p %c\n", *(a), *(a++));
printf("%p\n", *(b+2));

输出看起来像

0x73 s
0x74 t
0x72 r
0x69 i
0x6e n
0x67 g
0x72

此外,程序如何确定(b + 2)位于0x72。我认为它只会将2添加到b的起始地址,在本例中为0x73。

编辑:这不是未指定行为的情况。正如答案中所解释的那样,我错误地将值传递给地址格式说明符而不是指针本身。

2 个答案:

答案 0 :(得分:6)

尝试

printf("%p %c\n", (void *)a, *a);
a++;

并且高兴,连续的元素实际上是连续的!

您的代码出了什么问题:

  • 当您撰写*(a)时,您传递了printf当前字符的而不是其地址,然后由printf打印,就好像它一样是一个指针;您看到的十六进制值是"string"字符的字符代码而不是它们的地址(请注意,从格式字符串的预期传递给printf不同的参数是未定义的行为,事实上它产生了一些合理的输出是偶然的);
  • 第二个printf也会受到同样的错误影响;
  • 你会注意到我在这里也将分隔语句中的增量分开了;正如 haccks 指出的那样,因为它们最初还有另一个未定义行为的原因,因为函数调用不会在其参数的评估之间引入序列点;这意味着它是未定义的,首先评估哪一个,因此评估aprintf的第二个参数之前或之后是否递增。
  • 不推荐使用char *代替const char *指向字符串文字的指针;

答案 1 :(得分:1)

你不打印地址而是字符。 a是地址,*a是存储在该地址的值(char类型)。 0x73是小写's'的{​​{3}},依此类推。

如果您想打印地址,那么您的代码应如下所示:

char * a = "string";
char * b = a;
while (*a != '\0') {
    printf("%p %c\n", a, *a));       // address and value (char)
    a ++;
}

此外,printf("%p\n", *(b+2));打印的b[2]值为小写'r'ASCII code