简体   繁体   English

编译器如何确定位域结构的大小?

[英]How does compiler determine the size of a bitfield struct?

For example: 例如:

struct a {
    uint32_t    foreColor_ : 32;
    uint32_t    backColor_ : 32;
    uint16_t    lfHeight_ : 16;
    uint16_t    flags_: 4;
    bool    lfBold_: 1;
    bool    lfItalic_: 1;
    bool    lfUnderLine_: 1;
    bool    lfDashLine_: 1; 
    bool    lfStrike_: 1;
    bool    lfSubscript_: 1;
    bool    lfSuperscript_: 1;
};

is 16 bytes but 是16个字节但是

struct a {
    uint32_t    foreColor_ : 32;
    uint32_t    backColor_ : 32;
    uint16_t    lfHeight_ : 16;
    uint8_t     flags_: 4;
    bool    lfBold_: 1;
    bool    lfItalic_: 1;
    bool    lfUnderLine_: 1;
    bool    lfDashLine_: 1; //for ime 
    bool    lfStrike_: 1;
    bool    lfSubscript_: 1;
    bool    lfSuperscript_: 1;
};

is 12 bytes long. 是12个字节长。

I thought flags_ should have the same length, but it seems not. 我认为flags_应该有相同的长度,但似乎没有。

Why? 为什么?

The standard (9.6 of the working draft ) says this: 标准( 工作草案的 9.6)说:

specifies a bit-field; 指定一个位域; its length is set off from the bit-field name by a colon. 它的长度是通过冒号从位字段名称中设置的。 The bit-field attribute is not part of the type of the class member. bit-field属性不是类成员类型的一部分。 The constant-expression shall be an integral constant-expression with a value greater than or equal to zero. 常量表达式应为具有大于或等于零的值的整数常量表达式。 The constant-expression may be larger than the number of bits in the object representation ( 3.9 ) of the bit-field's type; 常量表达式可能大于位域类型的对象表示(3.9)中的位数; in such cases the extra bits are used as padding bits and do not participate in the value representation ( 3.9 ) of the bit-field. 在这种情况下,额外的比特用作填充比特,并且不参与比特字段的值表示(3.9)。 Allocation of bit-fields within a class object is implementation-defined. 类对象中位域的分配是实现定义的。 Alignment of bit-fields is implementation-defined . 位字段的对齐是实现定义的 Bit-fields are packed into some addressable allocation unit. 比特字段被打包到一些可寻址的分配单元中。 [ Note: bit-fields straddle allocation units on some machines and not on others. [注意:位字段跨越某些机器上的分配单元而不是其他机器上的分配单元。 Bit-fields are assigned right-to-left on some machines, left-to-right on others. 在某些机器上从右到左分配位字段,在其他机器上从左到右分配。 —end note] - 尾注]

(my emphasis) (我的重点)

So it will depend on your compiler. 所以这取决于你的编译器。 What appears to be happening in your case - and I would describe as fairly normal behaviour - is that it is only combining bitfields of the same type and then is packing the structure to a 4 byte boundary, so in the first case we have: 在您的情况下似乎正在发生的事情 - 我将其描述为相当正常的行为 - 是它只是组合相同类型的位域然后将结构打包到4字节边界,所以在第一种情况下我们有:

struct a {
    uint32_t    foreColor_ : 32; // 4 bytes (total)
    uint32_t    backColor_ : 32; // 8 bytes
    uint16_t    lfHeight_ : 16;  // 10 bytes
    uint16_t    flags_: 4;       // 12 bytes
    bool    lfBold_: 1;          // 13 bytes
    bool    lfItalic_: 1;
    bool    lfUnderLine_: 1;
    bool    lfDashLine_: 1; 
    bool    lfStrike_: 1;
    bool    lfSubscript_: 1;
    bool    lfSuperscript_: 1;   // still 13 bytes
};

Which is then padded to 16 bytes, and in the second we have: 然后填充到16个字节,在第二个字节中我们有:

struct a {
    uint32_t    foreColor_ : 32;  // 4 bytes (total)
    uint32_t    backColor_ : 32;  // 8 bytes
    uint16_t    lfHeight_ : 16;   // 10 bytes
    uint8_t     flags_: 4;        // 11 bytes
    bool    lfBold_: 1;           // 12 bytes
    bool    lfItalic_: 1;
    bool    lfUnderLine_: 1;
    bool    lfDashLine_: 1; 
    bool    lfStrike_: 1;
    bool    lfSubscript_: 1;
    bool    lfSuperscript_: 1;    // still 12 bytes
};

Which needs no padding and stays at 12 bytes. 它不需要填充,并保持12个字节。

It is compiler specific, the compiler is doing various alignments to optimize access to the fields. 它是特定于编译器的,编译器正在进行各种对齐以优化对字段的访问。

If you want (need to) rely on the alignement. 如果你想(需要)依赖于对方。 (like network header processing) You need to use #pragma push, pop. (比如网络头处理)你需要使用#pragma push,pop。

Or __ attribute __(packed) - which is a GCC extension. 或者__ attribute __(packed) - 这是一个GCC扩展。

struct {
...
} __attribute__(packed)

This will force the compiler to squash it. 这将迫使编译器压缩它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM