#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
来自指向同一结构项成员的指针?
答案 0 :(得分:0)
输出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个字节的差异。由于我们正在进行指针减法,因此差值为{byte offset difference} / {element size}。所以我们有16(字节差异)/ 4(sizeof(unsigned int))== 4.
如果sizeof(long int)
为4,那么结构可能会像这样布局:
struct test
{
unsigned int x; // 4 bytes
long int y; // 4 bytes
unsigned int z; // 4 bytes
};
在这种情况下输出为2。
请注意,虽然struct成员的顺序定义为顺序,但填充的布局是实现定义的。编译器可以随意填充。
来自C standard的第6.7.2.1节:
13 在结构对象中,非位字段成员和位字段所在的单元具有的地址 按声明的顺序增加。指向a的指针 结构对象,适当转换,指向其初始 成员(或者如果该成员是位字段,那么到单位 它居住在哪里),反之亦然。 可能有未命名的 在结构对象中填充,但不在其开头。
...
15 结构或联合的末尾可能有未命名的填充。