【问题标题】:What are the differences between #pragma pack(push, n)/#pragma pack(pop) and __attribute__((__packed__, aligned(n) )) on GCC?GCC 上的#pragma pack(push, n)/#pragma pack(pop) 和 __attribute__((__packed__,aligned(n) )) 有什么区别?
【发布时间】:2016-01-30 22:54:40
【问题描述】:

具体在 GCC 上(即都用 GCC 编译),以下两者的工作方式有什么区别?

struct foo1 {
    char a;
    int b;
} __attribute__((__packed__, aligned(n) ));

和:

#pragma pack(push, n)
struct foo2 {
    char a;
    int b;
};
#pragma pack(pop)

他们appear to behave differently:

foo1 f1;
foo2 f2;

int& i1 = f1.b; // ok
int& i2 = f2.b; // cannot bind packed field 'f2.foo2::b' to 'int&'

为什么一个有错误而另一个没有?至少内存布局是否相同?

【问题讨论】:

    标签: c++ c gcc memory-alignment


    【解决方案1】:

    您没有说明您使用的是哪个版本的 GCC,但您可以找到相应的手册 on-line。但是,它们在这些方面都非常兼容,因为属性和 pragma 的行为一旦定义,通常会跨版本维护以实现兼容性。我将从 GCC 4.9.3 的手册中引用具体的引文,目前是 GCC 4 系列的最新可用版本。特别是 type attributesstructure-packing pragmas 上的部分是相关的。

    GCC 手册中提到 #pragma pack 和朋友:

    #pragma 指令可更改随后定义的结构(零宽度位字段除外)、联合和类的成员最大对齐方式。

    (强调添加)。它说__attribute__((packed))

    附加到结构或联合类型定义的此属性指定结构或联合的每个成员(除了零宽度位字段)的放置以最小化所需的内存。

    上面写着__attribute__ ((aligned(n)))

    此属性指定指定类型的变量最小对齐方式,以字节为单位。

    (强调)。

    因此,不,#pragma pack(n),有或没有push,通常与将__attribute__((packed, aligned(n)) 附加到结构类型的含义不同。前者指定受影响结构的成员在n-byte 或更精细的边界上对齐。后者指定受影响结构的成员使用最小允许填充填充,并且为整个结构实例选择的对齐要求必须不小于n。它们不仅不一样,甚至不是很相似。

    您应该发现#pragma pack(1) 影响结构定义对实例布局的影响与将__attribute__((packed)) 附加到该结构的定义相同。然而,即使他们完成了相同的目标,他们也不是同一件事。两者的行为和效果都超出了 C++ 规范,GCC 完全有权在其他方面区别对待它们。

    但是,如果您想使用属性来影响结构成员的对齐方式,那么您需要在逐个成员的基础上应用至少一些属性。比如……

    struct foo1 {
        char a;
        int b __attribute__((aligned(n)));
    } __attribute__((packed));
    

    ...可能与...具有相同的效果

    #pragma pack(push, n)
    struct foo2 {
        char a;
        int b;
    };
    #pragma pack(pop)
    

    ...,取决于n

    【讨论】:

    • “您应该会发现 #pragma pack(1) 对结构定义的影响与将 __attribute__((packed)) 附加到该定义的效果相同”:但是,一个编译,另一个没有在 OP 发布的示例中。
    • @m.s.他们都用 g++ 4.4.7 对我编译得很好。再说一次,他原来的例子也是如此。尽管如此,我还是修改了我的答案,以在该领域缩小和锐化一点。
    猜你喜欢
    • 2015-11-19
    • 1970-01-01
    • 2012-08-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 2014-05-10
    相关资源
    最近更新 更多