是什么决定了两个结构构件之间的距离?

时间:2016-05-02 20:06:52

标签: c struct

#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,为什么我得到的结果不是2ptr2 - ptr1语句是否正确ptr1ptr2来自指向同一结构项成员的指针?

1 个答案:

答案 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 结构或联合的末尾可能有未命名的填充。