c结构中的压缩位字段 - GCC

Dan*_*hen 18 c gcc struct packed bit-fields

我在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
}
Run Code Online (Sandbox Code Playgroud)

为什么两个结构 - 完全相同 - 采用不同的字节数?

Mat*_*Mat 28

你的结构不是"完全一样".您的第一个具有三个连续的位字段,第二个具有一个位字段,一个(非位字段)int,然后是第二个位字段.

这很重要:连续(非零宽度)位字段合并到单个存储器位置,而位字段后跟非位字段是不同的存储器位置.

您的第一个结构有一个内存位置,第二个结构有三个.您可以b在第二个结构中获取该成员的地址,而不是第一个结构中的成员地址.对b成员的访问不会与第二个结构中的访问a或访问竞争c,但它们会在您的第一个结构中进行.

在位字段成员在一个sens中"关闭"之后立即具有非位字段(或零长度位字段),接下来将是不同的/独立的存储器位置/对象.编译器不能b像在第一个结构中那样将您的成员"打包" 在位字段内.


Joh*_*nck 17

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));
Run Code Online (Sandbox Code Playgroud)

常规int b必须与字节边界对齐.所以之前有填充.如果你把它放在c旁边a这个填充将不再是必要的.您可能应该这样做,因为访问非字节对齐的整数int b:32很慢.