ZHCUAQ1F july 2015 – april 2023
编译器支持以下类型属性:
使用 aligned 类型属性时,编译器会根据需要对结构体、联合体或其他类型的单个元素进行填充(这在结构体中很常见),从而实现所有元素按指定方式对齐。此外,任何派生类型都具有相同的对齐。例如:
struct __attribute__((aligned(32))) myStruct { char c1; int i; char c2; };
结构体和联合体类型都支持 packed 属性。如果使用了 --relaxed_ansi 选项,则它仅适用于对未对齐访问提供硬件支持的目标架构。
压缩结构的成员在存储时会尽可能靠近彼此,并会忽略通常为保持字对齐而添加的额外填充字节。例如,假定一个 4 个字节的字大小通常在成员 c1 和 i 之间具有 3 个填充字节,在成员 c2 后具有另外 3 个填充字节,因此总大小为 12 个字节:
struct unpacked_struct { char c1; int i; char c2;};
不过,压缩结构的成员是字节对齐的。因此,以下示例中成员之间或之后没有任何填充字节,总共为 6 个字节:
struct __attribute__((__packed__)) packed_struct { char c1; int i; char c2; };
因此,数组中的压缩结构会压缩在一起,数组元素之间没有填充字节。
在位字段上使用“packed”会覆盖位字段的 EABI 要求。对于非压缩位字段,位字段的声明类型会用于容器类型。对于打包位字段,不管声明类型如何,都会使用最小整型(bool 除外)。对于非压缩易失性位字段,位字段必须使用大小与声明类型相同的访问来进行访问。对于压缩易失性位字段,访问必须与实际容器类型具有相同的大小,并可能与声明类型的大小不同;另外,实际容器可能不对齐,并且可能跨多个对齐的容器边界,因此访问压缩易失性位字段时可能需要多次进行存储器存取。这还可能会影响结构体的总体大小;例如,如果该结构体仅包含位字段,它可能与位字段的声明类型不一样大。对于压缩和非压缩位字段,位字段都是位对齐,并与以下相邻位字段压缩在一起:没有填充字节,完全包含在至少是字节对齐的整数容器中;并且不会改变相邻非位字段结构成员的对齐方式。 有关位字段布局的说明,请参阅节 8.2.2。
“packed”属性只能应用于结构体或联合体类型的原始定义。它不能通过 typedef 用于已定义的非压缩结构,也不能用于结构体或联合体对象的声明。因此,任意给定结构体或联合体类型都只能是压缩或非压缩,并且该类型的所有对象都会继承其 packed 或 non-packed 属性。
“packed”属性不能递归应用到压缩结构体中包含的结构体类型。因此,在以下示例中,成员会保留与上方第一个示例相同的内部布局。c 和 s 之间没有填充字节,因此 s 在未对齐的边界上:
struct __attribute__((__packed__)) outer_packed_struct { char c; struct unpacked_struct s; };
以隐式或显式方式将压缩结构体成员的地址作为指针投射到除无符号字符以外的任意非紧凑类型都是非法的。在以下示例中,p1、p2 和对 foo 的调用都是非法的。
void foo(int *param);
struct packed_struct ps;
int *p1 = &ps.i;
int *p2 = (int *)&ps.i;
foo(&ps.i);
不过,以显式方式将压缩结构体成员的地址作为指针投射到无符号字符则是合法的。
unsigned char *pc = (unsigned char *)&ps.i;
TI 编译器还支持枚举类型的 unpacked 属性,让您可以指示表现形式为不小于 int 的整型;也就是说,它不是 packed。