最小位域大小

Smallest size of bit field

我在理解 sizeof 返回的结果时遇到一些问题。

假设我有两个结构:

typedef struct{
    unsigned int  age    : 4;
    unsigned char gender : 1;
    unsigned int  size   : 2;
} child_t;

typedef struct{
    unsigned int  age    : 4;
    unsigned char gender : 1;
    unsigned int  size   : 2;
} __attribute__((packed)) child_t_packed;

https://coliru.stacked-crooked.com/view?id=10866c66fe82f4e4

你能解释一下为什么第一个结构的大小是 4 个字节吗?

可能我错了,但我预计是 2 个字节。 (第一行4位,第二行3位)。

打包版本忽略对齐,在第二种情况下sizeof(child_t_packed) = 1 byte. 这是否意味着 1 个字节是 child_t_packed 类型的变量在内存中可能占用的最小大小?或者最小值可以是 7 位?

在标准 C++ 中,结构的最小可能大小为 1 char(至少 8 位)。因此,即使像 __attribute__((packed)) 这样的扩展也被迫产生大小为 1.

的结构

此外,几乎所有关于位域布局的内容都是实现定义的。

在这个例子中,GCC 似乎只是选择最大指定成员类型 (int) 的对齐方式来进行位域对齐。

如果将 int 更改为 short,则 sizeof(child_t) 将产生 2:

typedef struct{
    unsigned short age    : 4;
    unsigned char  gender : 1;
    unsigned short size   : 2;
} child_t;

https://coliru.stacked-crooked.com/a/3db0b400312e3d2c

child_t 的大小是四个字节,因为实现决定将 structunsigned int 对齐,即 age 和 [=15] 的类型=].

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.

[class.bit]

如果 child_t 仅由 unsigned char 位域成员组成,则对齐将是 unsigned char 的对齐,而整个 struct 将(很可能,它仍然是实现定义的)适合单个字节。

typedef struct{
    unsigned char age     : 4;
    unsigned char gender  : 1;
    unsigned char size    : 2;
} child_t_char;

https://godbolt.org/z/MGKPqGPKq

child_t_packed 的大小为 1,因为我们使用 packed 属性强制执行最小填充。

The packed attribute specifies that a structure member should have the smallest possible alignment—one bit for a bit-field and one byte otherwise, unless a larger value is specified with the aligned attribute. The attribute does not apply to non-member objects.

GCC 11 documentation on variable attributes

由于4+1+2位可以放入一个字节,所以大小为1。这意味着 child_t_packed 类型的对象将在内存中占用 正好 个字节。