C语言 混淆数组元素地址



我希望看到 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 %08xn", p, atbl, &atbl[0], &atbl[1], &atbl[2]);

但我得到以下结果:

P - DAE83240
ATBL - DAE83140
&atbl[0] - DAE83140
&atbl[1]- DAE83150
&ATBL[2] - DAE83160

任何提示?

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

这应该是:

p = atbl + 1;

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

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

指针算术会自动考虑指向对象的大小;你不需要乘以sizeof(struct a)

atbl ,在隐式数组到指针转换之后,是类型为 struct a* 的指针。 atbl + 2点 2 struct a元素超过atbl指向的地址。

此外,不要使用 %x 打印指针值;而是将指针值强制转换为 void* 并使用 %p

而不是

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

你需要

p = (atbl  + 1 );  

如果结构atbl的起始地址是1000(假设),则向其添加1会将其增加16个单位,并将p指向1016(假设unsigned int 4字节)。它不会按1单位递增p1001 )此外,您使用了错误的说明符来打印地址。这将调用未定义的行为

C11: 7.21.6 格式化输入/输出函数:

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

使用%p说明符打印地址。您的printf语句应如下所示:

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

推荐阅读:指针算术

最新更新