混淆数组元素地址

时间:2014-01-08 18:54:56

标签: c arrays pointers

我希望看到p和& atbl [1]打印相同的值(元素1的位置)但它不同

struct a {
    unsigned int  el[4];
};

struct a atbl[3] = {
  {0x12131415, 0x01030507, 0x01030507, 0x16171819},
  {0xa2a3a4a5, 0x02020202, 0x02020202, 0xa6a7a8a9},
  {0xb2c3d4e5, 0x02020202, 0x02020202, 0x0badcafe},
};  

struct a * p;
// read address of element 1 in atbl
p = (atbl  + (1 * sizeof(struct a)));
printf("%08x %08x %08x %08x %08x\n", p, atbl, &atbl[0], &atbl[1], &atbl[2]);

但我得到以下结果:

p - dae83240
atbl - dae83140
& atbl [0] - dae83140
& atbl [1] - dae83150
& atbl [2] - dae83160

任何提示?

3 个答案:

答案 0 :(得分:4)

// read address of element 1 in atbl
p = (atbl  + (2 * sizeof(struct a)));

这应该是:

p = atbl + 1;

将一个添加到已指向第一个条目的内容将使其指向第二个条目。因此,添加两个会使它指向第三个条目。您希望它指向第二个条目,因此您需要添加一个。

此外,您不会乘以大小,因为指针已经知道它指向的东西的大小。添加一个已经指向下一个对象。

答案 1 :(得分:3)

指针算法自动计算指向对象的大小;您不需要乘以sizeof(struct a)

在隐式数组到指针转换之后,

atbl是类型为struct a*的指针。 atbl + 2点{2} struct a个元素超出atbl指向的地址。

另外,不要使用%x来打印指针值;相反,将指针值强制转换为void*并使用%p

答案 2 :(得分:1)

而不是

p = (atbl  + (1 * sizeof(struct a))); 

你需要

p = (atbl  + 1 );  

如果结构atbl的起始地址是1000(让我们说),那么将1添加到它会增加16单位和p点到1016(假设4unsigned int个字节。 p单位(1)不会增加1001 此外,您使用错误的说明符来打印地址。这将调用未定义的行为

C11:7.21.6格式化输入/输出功能:

  

如果转换规范无效,行为未定义 .282)如果任何参数不是相应转换规范的正确类型,行为是   未定义即可。

使用%p说明符打印地址。您的printf声明应该是:

printf("%8p %8p %8p %8p %8p\n", (void *)p, (void *)atbl, (void *)&atbl[0], (void *)&atbl[1], (void *)&atbl[2]);  

建议阅读:Pointer Arithmetic