我对以下代码如何在内存中布局感到困惑:
struct Thing { union { unsigned value:24; uint8_t bytes[3]; }; Thing(int v) :value(v) {} void foo() { printf("Thing %p value=%d !\n",this,value); } } __attribute__((__packed__));
在Linux上的gcc 3.3,4.3或4.6上(没有我能想到的任何特殊选项 – 在4.6上只有“-Wall -g”),结构的大小总是4:
$pahole ./union struct Thing { union { unsigned int value; /* 4 */ unsigned char bytes[3]; /* 3 */ }; [...]
我们在这里有一些类似的代码,其中我们有无符号值:结构中有24个,有人添加了联合,并且无意中将结构的大小从3增加到4个字节.
如果我尝试将union定义为“packed”,同样的事情会发生 – size仍然是4.这个行为是否符合C规范?会有什么解释?
稍后编辑:将“C spec”替换为“C spec”.
解决方法
您错过了匿名联盟的打包属性.考虑这个例子:
#define PACKED __attribute__((__packed__)) struct S1 { unsigned value:24; } PACKED ; struct S2 { union { char a[3]; unsigned value:24; }; } PACKED ; struct S3 { union { char a[3]; unsigned value:24; } PACKED ; }; int main() { std::cout << sizeof(S1) << std::endl; std::cout << sizeof(S2) << std::endl; std::cout << sizeof(S3) << std::endl; }
输出:
3 4 3
打包属性有点奇怪,我总是尝试测试每个可能的组合以获得正确的结果.