【问题标题】:Struct packing in GCC on 32-bit doesn't work?在 32 位的 GCC 中结构打包不起作用?
【发布时间】:2013-01-14 17:09:35
【问题描述】:

我在一个项目中继承了一些第三方代码。它由一个头文件和一个没有源的二进制库组成,所以我不能用不同的设置重新编译它。

标头使用编译时类似断言的技巧(typedef如果表达式失败,则使用负大小数组)来确保正确的结构对齐,但它似乎不适用于 32 位模式。

这是一个捕获整个问题的独立小程序:

#include <stdio.h>
#include <stddef.h>

#pragma pack(push, 8)
struct test {char _; long long a;};
typedef char pack_test[(offsetof(test, a) == 8) ? 1 : -1];
#pragma pack(pop)

int main(int argc, char *argv[])
{
        printf("%d\n", offsetof(test, a));
        return 0;
}

上面的代码无法在 clang 3.0 和任何我可以快速上手的最新 gcc 版本(4.5 到 4.7)上编译:打包 pragma 根本没有任何效果。编译器不断将成员 a 对齐到 4 个字节(您可以通过注释掉 typedef 来检查)。

这是为什么呢?我怎样才能修复代码,以使这个断言不会失败并保持它与 ABI 兼容,同时又不必遍历标头中的所有结构并将 attributes 附加到它们的尾部?

【问题讨论】:

    标签: c++ gcc struct g++ pragma


    【解决方案1】:

    在 32 位系统上,long long 可能不需要八个字节的对齐,四个就足够了。毕竟,您仍然从内存中获取两个完整的字,无论第一个字是八字节对齐还是四个。

    您可以尝试使用属性强制八字节对齐

    struct test { char _; long long a __attribute__ ((aligned(8))); };
    

    (可能是错的,我对gcc的属性不熟悉)

    当然,您也可以在struct 中添加一个虚拟成员以确保所需的对齐方式

    struct test { char _; char dummy[7]; long long a; }
    

    这应该在实践中起作用。

    【讨论】:

    • 是的,就是这样!我添加了__attribute__ ((aligned (8)),它现在可以工作了。谢谢!
    猜你喜欢
    • 2014-11-07
    • 2011-10-04
    • 1970-01-01
    • 2010-12-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    相关资源
    最近更新 更多