4

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

标头使用编译时类似断言的技巧(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 个字节(您可以通过注释typedefout 来检查)。

这是为什么?如何修复代码,以使该断言不会失败并使其与 ABI 兼容,同时不必遍历标头中的所有结构并将attributes 附加到它们的尾部?

4

1 回答 1

4

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

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

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

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

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

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

这应该在实践中起作用。

于 2013-01-14T17:11:26.123 回答