我在linux上使用c中的结构。 我开始使用位字段和"打包"属性和我遇到了一个奇怪的行为:
struct t1
{
int a:12;
int b:32;
int c:4;
}__attribute__((packed));
struct t2
{
int a:12;
int b;
int c:4;
}__attribute__((packed));
void main()
{
printf("%d\n",sizeof(t1)); //output - 6
printf("%d\n",sizeof(t2)); //output - 7
}
为什么两个结构完全相同 - 采用不同的字节数?
答案 0 :(得分:22)
你的结构不是“完全一样”。你的第一个有三个连续的位字段,第二个有一个位字段,一个(非位字段)int,然后是第二个位字段。
这很重要:连续(非零宽度)位字段合并为单个存储单元,而位字段后跟非位字段是不同的存储单元。
您的第一个结构有一个内存位置,第二个结构有三个。您可以在第二个结构中获取b
成员的地址,而不是第一个结构中的地址。对b
成员的访问不会与第二个结构中的a
或c
进行竞争,但它们会在您的第一个结构中进行访问。
在比特字段成员“关闭”它之后立即具有非比特字段(或零长度比特字段),接下来将是不同的/独立的存储器位置/对象。编译器不能像在第一个结构中那样“封装”位域内的b
成员。
答案 1 :(得分:16)
struct t1 // 6 bytes
{
int a:12; // 0:11
int b:32; // 12:43
int c:4; // 44:47
}__attribute__((packed));
struct t1 // 7 bytes
{
int a:12; // 0:11
int b; // 16:47
int c:4; // 48:51
}__attribute__((packed));
常规int b
必须与字节边界对齐。所以之前有填充。如果您将c
放在a
旁边,则不再需要此填充。您应该这样做,因为访问像int b:32
这样的非字节对齐的整数很慢。