设想一个由32位,16位和8位成员值组成的结构。 成员值的顺序是每个成员都在自然边界上。
struct Foo { uint32_t a; uint16_t b; uint8_t c; uint8_t d; uint32_t e; };
成员alignment和填充规则logging为Visual C ++。 在VC ++上的sizeof(Foo),上面的结构是可预测的“12”。
现在我可以肯定,这个规则是没有关于填充和alignment的假设,但是实际上其他操作系统上的其他编译器是否也有类似的保证?
如果没有,GCC上是否有相当于“#pragma pack(1)”的?
在实际提供这些类型的系统上,它很有可能工作。 比方说,一个36位的系统,这些类型首先是不可用的。
GCC提供了一个属性
__attribute__ ((packed))
效果类似。
一般来说,你是正确的,这不是一个安全的假设,虽然你会经常得到你期望在许多系统上的包装。 当你使用gcc时,你可能想在你的类型上使用packed
属性。
例如
struct __attribute__((packed)) Blah { /* ... */ };
实际上,在任何存在uintXX_t
类型的系统上,您将得到所需的对齐方式,而不填充。 不要扔在丑陋的海湾合作委员会,以保证它。
编辑:为了详细说明为什么使用attribute packed
或aligned
可能是有害的,它可能会导致整个结构在作为较大结构的成员或堆栈中使用时未对齐。 这肯定会损害性能,而在非x86机器上,会产生更大的代码。 这也意味着将指针指向结构的任何成员是无效的,因为通过指针访问值的代码不会意识到它可能会错位,从而可能会出错。
至于为什么没有必要,请记住这个attribute
是特定于gcc和gcc-workalike编译器的。 C标准没有定义未定义的或未指定的。 它是实现定义的 ,这意味着需要实现来进一步指定和记录它的行为。 gcc的行为始终是将每个结构成员对齐到其自然对齐的下一个边界上(在结构之外使用时,它必须具有相同的对齐方式,这必然是一个平均分割类型大小的数字) 。 由于attribute
是一个gcc功能,如果你使用它,你已经假设一个类似gcc的编译器,但是假设你已经有了你想要的对齐方式。