含位域的结构体对齐疑问:sizeof(A)为何为12?如何规避?
结构体
sizeof(A)为12的原因分析 你的计算错误在于忽略了位域的基础类型对齐规则和结构体成员的对齐要求,具体拆解如下:
- 位域的存储规则
- 前7个位域(
x_0到x_6)的基础类型是int(通常为4字节/32位),即使这些位总共只占12位,也会占用一整个int的存储空间(4字节),剩余20位会被编译器填充为空白,无法和后续不同基础类型的位域共用存储单元。 - 接下来的
uint16_t pad:4基础类型是uint16_t(2字节/16位),占用一个独立的2字节单元,仅使用4位,剩余12位同样被填充。
- 前7个位域(
- 成员对齐与总大小计算
uint16_t y_1是完整的2字节类型,需对齐到2字节边界,紧随pad的2字节单元之后,占用2字节。此时已用空间为4+2+2=8字节。float y_2是4字节类型,需对齐到4字节边界(结构体的最大对齐单位由float决定,为4字节),8字节正好是4的倍数,所以y_2直接占用后续4字节。- 总大小为
8+4=12字节,且12是4的倍数,符合结构体对齐要求。
优化方案(按
float对齐的前提下减小体积) 要避免不必要的填充,核心是优化位域的基础类型:
将前7个位域的基础类型改为uint16_t,让它们和pad共用同一个2字节存储单元:
struct A { uint16_t x_0 : 1; uint16_t x_1 : 1; uint16_t x_2 : 1; uint16_t x_3 : 2; uint16_t x_4 : 2; uint16_t x_5 : 2; uint16_t x_6 : 3; uint16_t pad : 4; // 1+1+1+2+2+2+3+4=16,刚好填满一个uint16_t uint16_t y_1; float y_2; };
此时位域部分仅占2字节,加上y_1的2字节、y_2的4字节,总大小为2+2+4=8字节,且8是4的倍数,完全符合float的对齐要求。
内容的提问来源于stack exchange,提问作者Vovyaklya
相关产品推荐
相关产品推荐

