代码之家  ›  专栏  ›  技术社区  ›  my_question

如何理解结构填充?

c
  •  0
  • my_question  · 技术社区  · 2 年前

    我学习过 The Lost Art of Structure Packing ,但是下面的实验把我弄糊涂了。

    这是代码:

    #include <stdio.h>
    
    int main(int argc, char **argv)
    {
        struct a_t {
            char aa;
        };
    
        struct b_t {
            int bb;
            int bbb;
        };
    
        struct c_t {
            struct a_t  parent_a;
            struct b_t  parent_b;
            char cc;
        };
    
        struct c_t c;
        printf("sizeof(a_t)=%d\n", sizeof(struct a_t));
        printf("sizeof(b_t)=%d\n", sizeof(struct b_t));
        printf("c address=%p\n", &c);
        printf("c's parent_a=%p\n", &(c.parent_a));
        printf("c's parent_b=%p\n", &(c.parent_b));
        printf("c + sizeof(a_t)=%p\n", (struct b_t *)(&c + sizeof(struct a_t)));
    
        return 0;
    }
    

    输出如下:

    sizeof(a_t)=1
    sizeof(b_t)=8
    c address=0x7fff9bca7680
    c's parent_a=0x7fff9bca7680
    c's parent_b=0x7fff9bca7684
    c + sizeof(a_t)=0x7fff9bca7690
    

    输出中的最后3行令人惊讶:

    1. c's parent_a=0x7fff9bca7680 ,这是意料之中的事。parent_a地址等于结构变量c的地址。
    2. c's parent_b=0x7fff9bca7684 ,这是一个惊喜,parent_b的大小是8字节,为什么它的地址不是8的倍数?
    3. c + sizeof(a_t)=0x7fff9bca7690 ,这是一个惊喜,这超出了c的地址16个字节! struct a_t 大小为1字节,我原以为它是0x7fff9bca7681。

    你能发光吗?

    1 回复  |  直到 2 年前
        1
  •  2
  •   Mark Tolonen    2 年前

    答案2。 c_t 由于其最大成员的大小,只需要4字节对齐。

    答案3。由于指针数学, &c 是指向 c_t 其大小为16,因此向该指针加1将向该地址加16个字节。

    的大小 c_t 是16,因为 a_t 大小为1,3字节的填充要对齐 b_t ,b_t的大小为8(共12),则 char cc 大小为1,但结尾需要3个字节的填充(总共16个),因此如果 c_t 在数组中使用时,它仍将使其所有成员在4字节边界(最大成员的大小)上对齐。