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