You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结构体填充理解困惑:结构体成员地址与指针运算疑问

结构体内存布局与指针运算疑问解答

实验代码

#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

疑问与解答

疑问2:parent_b的地址为0x7fff9bca7684,并非8的倍数,而parent_b大小为8字节,对此感到疑惑

结构体的对齐核心规则是:成员的起始地址必须对齐到该成员类型对齐要求的整数倍,而结构体的对齐要求由其内部最大的基础数据类型成员决定。

  • struct b_t的成员是两个int(通常占4字节),因此b_t的对齐要求是4字节,而非8字节。
  • parent_a占1字节,为了满足parent_b的4字节对齐要求,编译器会在parent_a后填充3字节,因此parent_b的起始地址为0x7fff9bca7680 + 1 + 3 = 0x7fff9bca7684,刚好是4的倍数,完全符合对齐规则。
  • sizeof(b_t)=8是因为两个int各占4字节,总大小刚好是对齐后的结果,和对齐要求本身无关。

疑问3:&c + sizeof(struct a_t)的结果为0x7fff9bca7690,超出c的地址16字节,而struct a_t大小仅为1字节,与预期不符

这是对C语言指针运算规则的误解:指针加法的偏移量是「加数 × 指针指向类型的大小」,而非直接累加字节数。

  • &c是struct c_t*类型,sizeof(struct c_t)的计算结果是16字节(布局:1字节parent_a + 3字节填充 + 8字节parent_b + 1字节cc + 7字节填充,总大小对齐到结构体的对齐边界)。
  • sizeof(struct a_t)=1,因此&c + sizeof(struct a_t)等价于&c + 1,按照指针运算规则,实际偏移量是1 × sizeof(struct c_t) = 16字节,所以结果是0x7fff9bca7680 +16 = 0x7fff9bca7690。
  • 如果想实现「从&c的地址偏移1字节」的效果,需要先将指针转换为char*类型再做加法:(struct b_t*)((char*)&c + sizeof(struct a_t)),这样结果才会符合你的预期。

内容的提问来源于stack exchange,提问作者my_question

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:54:34