ZHCADC3B February 2019 – October 2023
C28x EABI 采用来自 IA64 C++ ABI 的位字段布局。除非明确指出,否则以下说明与该标准一致。
位字段的声明类型是出现在源代码中的类型。为了保存位字段的值,C 和 C++ 标准允许实现分配任何大得足以容纳位字段的可寻址存储单元,这不需要与声明类型相关。可寻址存储单元通常称为容器类型,我们在本文档中也这样称呼它。容器类型是位字段压缩和对齐方式的主要决定因素。
为了提高效率,编译器可以访问类型与声明类型或容器类型不匹配的位字段。声明类型和容器类型被严格用于确定位字段压缩和对齐。用于实际加载位字段的类型是访问类型。它可以是较窄的类型,根据位字段的大小和偏移量计算得出。例如,在下面的示例中,容器类型为 32 位,但位字段将使用 16 位访问加载:
struct S
{
long :16;
long bf:16;
};
C89、C99 和 C++语言标准对于声明类型有不同的要求:
C89 | int、unsigned int、signed int |
C99 | int、unsigned int、signed int、_Bool 或“其他一些实现定义类型” |
C++ | 任何整型或枚举类型,包括 bool |
严格 C++ 中没有 long long 类型,但由于 C99 包含该类型,C++ 编译器通常支持该类型作为扩展。C99 标准不要求实现支持位字段的 long 或 long long 声明类型,但由于 C++ 允许这种实现,因此 C 编译器也支持这种类型的情况并不少见。
位字段的值完全包含在其容器中,不包含任何填充位。容器根据其类型正确对齐。包含字段的结构对齐方式受到容器对齐方式的影响,影响方式与该类型的成员对象相同。这也适用于未命名字段,这与 IA64 C++ ABI 不同。容器可以包含其他字段或对象,并且可以与其他容器重叠,但为任何一个字段保留的位,包括用于超大字段的填充位,绝不会与另一个字段的位重叠。
在 C28x EABI 中,位字段的容器类型是其声明类型,但有一个例外。C++ 允许所谓的超大位字段,这些字段的声明大小大于声明类型。在这种情况下,容器是不大于字段的声明大小的最大的整型。
布局算法保持下一个可用位,这是分配位字段的起点。布局算法中的步骤如下:
在小端字节序模式下,容器从 LSB 向 MSB 填充。C28x 仅使用小端字节序模式。
零长度位字段强制结构的以下成员对齐到与声明类型对应的下一个对齐边界,并影响结构对齐。
C28x EABI 将 plain int 的声明类型视为 signed int。