结构件对齐 - 是否可以假设没有填充

struct member alignment - is it possible to assume no padding

本文关键字:假设 填充 构件 对齐 是否 结构      更新时间:2023-10-16

>想象一个由 32 位、16 位和 8 位成员值组成的结构。其中,成员值的顺序是每个成员都位于其自然边界上。

struct Foo
{
    uint32_t a;
    uint16_t b;
    uint8_t c;
    uint8_t d;
    uint32_t e;
};

记录了可视C++的成员对齐和填充规则。 sizeof(Foo( 在 VC++ 上,上面的结构可以预见地是"12"。

现在,我很确定规则是不应该对填充和对齐做出任何假设,但在实践中,其他操作系统上的其他编译器是否做出类似的保证?

如果没有,GCC 上是否有等效的"#pragma pack(1("?

实际上,在存在uintXX_t类型的任何系统上,您将获得所需的对齐方式,无需填充。不要抛出丑陋的gcc主义来试图保证它。

编辑:详细说明为什么使用attribute packedaligned可能是有害的,当用作较大结构的成员或在堆栈上时,可能会导致整个结构错位。这肯定会损害性能,并且在非 x86 计算机上,将生成更大的代码。这也意味着将指针指向结构的任何成员都是无效的,因为通过指针访问值的代码不会意识到它可能未对齐,因此可能会出错。

至于为什么没有必要,请记住,attribute特定于 gcc 和 gcc-workalike 编译器。C 标准不会未定义或未指定对齐方式。它是实现定义的,这意味着实现需要进一步指定和记录它的行为方式。GCC 的行为是,并且一直是,将每个结构成员对齐在其自然对齐的下一个边界上(与在结构外部使用时的对齐方式相同,它必然是一个平均划分类型大小的数字(。由于attribute是一个 gcc 功能,如果你使用它,你已经假设了一个类似 gcc 的编译器,但通过假设你已经有了你想要的对齐方式。

一般来说,您是正确的,这不是一个安全的假设,尽管您通常会在许多系统上获得您期望的包装。使用 gcc 时,您可能希望在类型上使用 packed 属性。

例如

struct __attribute__((packed)) Blah { /* ... */ };

在实际提供这些类型的系统上,它极有可能工作。例如,在36位系统上,这些类型首先不可用。

GCC 提供了一个属性
 

__attribute__ ((packed))

具有类似的效果。