struct member alignment - 是否可以假设没有填充

sel*_*bie 10 c c++ linux gcc

想象一个由32位,16位和8位成员值组成的结构.成员值的排序使得每个成员都在其自然边界上.

struct Foo
{
    uint32_t a;
    uint16_t b;
    uint8_t c;
    uint8_t d;
    uint32_t e;
};
Run Code Online (Sandbox Code Playgroud)

为Visual C++ 记录了成员对齐和填充规则.VC++上的sizeof(Foo)上面的结构可以预测为"12".

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

如果没有,GCC上是否有相同的"#pragma pack(1)"?

CB *_*ley 7

一般来说,你是正确的,这不是一个安全的假设,虽然你经常得到你期望在许多系统上的包装.packed使用gcc时,您可能希望在类型上使用该属性.

例如

struct __attribute__((packed)) Blah { /* ... */ };
Run Code Online (Sandbox Code Playgroud)


Bo *_*son 6

在实际提供这些类型的系统上,很有可能工作.比如说,36位系统首先不会提供这些类型.

GCC提供了一个属性
 

__attribute__ ((packed))

具有类似的效果.


R..*_*R.. 6

实际上,在uintXX_t存在类型的任何系统上,您将获得所需的对齐而没有填充.不要投入丑陋的gcc-isms来保证它.

编辑:详细说明使用它可能有害的原因,attribute packed或者当用作较大结构或堆栈的成员时aligned,可能导致整个结构未对齐.这肯定会损害性能,在非x86机器上,会产生更大的代码.它还意味着将指针指向结构的任何成员是无效的,因为通过指针访问该值的代码将不会意识到它可能未对齐,从而可能出错.

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