关于__packed__修饰的结构体abc_t的sizeof计算结果疑问
为啥用了
__attribute__((__packed__))结构体大小还是20字节? 先把你的代码贴出来方便分析:
typedef struct abc { double a; int b; char c; int d; }__attribute__((__packed__))abc_t; int main() { //To do place code abc_t tmp; printf("The size is %d\n",sizeof(tmp)); return 0; }
你计算的8+4+1+4=17字节是理论上packed生效后的大小,但实际得到20字节,最可能的原因是你用的编译器不支持GCC风格的__attribute__((__packed__))属性,比如微软的MSVC编译器:
情况1:使用MSVC编译器
MSVC完全不认识__attribute__((__packed__))这个语法,会直接忽略这个属性,你的结构体就会按照默认的对齐规则来分配内存:
double a占8字节(默认对齐到8字节边界)int b占4字节(对齐到4字节边界,接在a后面刚好是8字节位置,没问题)char c占1字节(从12字节位置开始)- 为了让后面的
int d满足4字节对齐要求,编译器会在c后面填充3字节,把位置拉到16字节 int d占4字节(16-19字节)- 总大小就是8+4+1+3+4=20字节,和你看到的结果完全一致。
如果是用MSVC,想要禁用填充,得用它自己的语法:#pragma pack(1),比如:
#pragma pack(1) typedef struct abc { double a; int b; char c; int d; } abc_t; #pragma pack() // 恢复默认对齐 int main() { abc_t tmp; printf("The size is %zu\n",sizeof(tmp)); // 注意用%zu输出size_t类型 return 0; }
这样编译出来的结构体大小就是17字节了。
情况2:使用GCC/Clang等支持__attribute__((__packed__))的编译器
如果是用GCC或Clang,正常情况下你的代码应该输出17字节。如果还是得到20字节,可能是这几个小问题:
- 属性位置写错了:虽然你写的位置是合法的,但有些旧版本的编译器可能要求把
__attribute__((__packed__))放在struct关键字后面,比如:typedef struct __attribute__((__packed__)) abc { double a; int b; char c; int d; } abc_t; - 编译选项影响:比如开启了某些强制对齐的编译选项,或者目标平台有特殊的内存对齐要求(比如某些嵌入式平台不允许非对齐访问,编译器会强制填充)。
- printf格式符错误:
sizeof返回的是size_t类型,用%d输出在64位系统上可能会有类型不匹配的问题,建议换成%zu,避免输出错误的数值。
内容的提问来源于stack exchange,提问作者Maddy
相关产品推荐
相关产品推荐

