#include <stdio.h>
struct test
{
unsigned int x;
long int y;
unsigned int z;
};
int main()
{
struct test t;
unsigned int *ptr1 = &t.x;
unsigned int *ptr2 = &t.z;
printf("%d", ptr2 - ptr1);
return 0;
}
该程序的输出在我的系统上4
,为什么我得到这个结果而不是2
?ptr2 - ptr1
语句是否正确,因为ptr1
和ptr2
来自指向同一结构项成员的指针?
此输出4
的原因与每种类型的大小以及结构填充和对齐方式有关。
在我的系统上,sizeof(unsigned int)
是 4,sizeof(long int)
是 8,sizeof(struct test)
是 24。 因此,为了确保 64 位字段位于 64 位边界上,结构的物理布局如下所示:
struct test
{
unsigned int x; // 4 bytes
// 4 bytes padding
long int y; // 8 bytes
unsigned int z; // 4 bytes
// 4 bytes padding
};
因此,当您取x
的偏移量和z
的偏移量之间的差值时,有16个字节的差异。 由于我们正在做指针减法,因此差值的值是{字节偏移差}/{元素大小}。 所以我们有 16(字节差(/4(sizeof(无符号整数((== 4。
如果sizeof(long int)
是 4,那么结构体的布局可能会是这样的:
struct test
{
unsigned int x; // 4 bytes
long int y; // 4 bytes
unsigned int z; // 4 bytes
};
在这种情况下,输出将为 2。
请注意,虽然结构成员的顺序定义为顺序,但填充的布局是实现定义的。 编译器可以根据需要自由填充。
从C标准第6.7.2.1节:
13 在结构对象中,非位字段成员和位字段所在的单元具有以下地址: 增加声明顺序。 指向 结构对象,适当转换,指向其初始 成员(或者,如果该成员是位字段,则到单元 它所在的位置(,反之亦然。 可能有未命名的 在结构对象中填充,但不在其开头填充。
。
15结构或联合的末端可能有未命名的填充。