结构填充编译标志

Posted

技术标签:

【中文标题】结构填充编译标志【英文标题】:structure padding compile flag 【发布时间】:2014-05-22 05:13:01 【问题描述】:
typedef struct
    char        t1;
    long long   t2;
    char        t3;
struct_size_test;

printf("sizeof(long long)==[%ld]\n", sizeof(long long));
printf("sizeof(char)==[%ld]\n", sizeof(char));
printf("sizeof(struct_size_test)==[%ld]\n", sizeof(struct_size_test));

struct_size_test 在 ios 和 OS X gcc 中的结果是不同的。 iOS 中的结果是

sizeof(long long)==[8]
sizeof(char)==[1]
sizeof(struct_size_test)==[24]

但是 OS X gcc 中的结果是

sizeof(long long)==[8]
sizeof(char)==[1]
sizeof(struct_size_test)==[16]

我搜索了这个并找到了一些建议,将“-malign-double”添加为 gcc 编译标志。 但它显示了

clang: error: unknown argument: '-malign-double' [-Wunused-command-line-argument-hard-error-in-future]
clang: note: this will be a hard error (cannot be downgraded to a warning) in the future

知道如何同步 iOS 和 OS X 的结构填充吗? 非常感谢!

【问题讨论】:

你想在这里做什么?如果您尝试使用结构填充,那么您很可能正在尝试一些非常错误或愚蠢的事情。 【参考方案1】:

您可以使用预处理器指令为结构指定字节对齐方式,因此编译器不会进行填充:

#pragma pack(1)

typedef structchar t1;long long t2;char t3;struct_size_test;

#pragma options align=reset

如果结构定义在一个不能更改的头文件中,比如 test.h:

//test.htypedef structchar t1;long long t2;char t3;struct_size_test;

当你包含 test.h 时,你可以这样做:

#pragma pack(1)#include test.h#pragma options align=reset

我在自己的代码中使用过这种方法。

请记住,上述解决方案实际上不是编译器标志,而是与您请求的效果相同的预处理器指令。希望这可以帮助。

【讨论】:

严格来说这不是一个预处理器指令,因为这个特定的指令会被预处理器忽略,而是由编译器解释。【参考方案2】:

我认为答案应该是你肯定不想这样做。

您可以尝试 nneonneo 的解决方案或将 __attribute__((packed)) 添加到您的结构中,以使结构在 OS X 和 iOS 上具有相同的大小,但请记住,这是编译器特定的功能,会降低您的代码的可移植性

此外,如果您确实更改了填充,由于未满足对齐要求,您的程序可能会在任一架构(尤其是 iOS/ARM)上崩溃或运行效率降低。一些 ARM 架构(不确定 iDevices)不允许未对齐的读取/写入,如果运行速度不慢(因为需要两次内存读取而不是一次),则会彻底崩溃。

一种解决方法可能是使用最高公共对齐方式(似乎是 8),这只会占用更多空间。但这仍然是 hacky 和不可移植的。

你为什么要这样做?

编辑:nneonneo 的答案可能应该是这样的:

typedef struct
    char        t1 __attribute__ ((aligned (8)));
    long long   t2 __attribute__ ((aligned (8)));
    char        t3 __attribute__ ((aligned (8)));
 struct_size_test;

【讨论】:

不行,我不能用__attribute__((packed)),结构大小必须和iOS显示的完全一样。该结构已经为许多团队成员的使用定义。所以结构不能改变。 为什么它必须是特定的尺寸?您是在汇编代码中使用结构还是什么? 将它用于 TCP 通信,因此它在两个不同的平台上。而且TX平台是固定的,不能改。 我认为最好有一个可移植的序列化和序列化例程,它接收原始字节并将其转换为该架构的内部表示,而不是尝试使用 struct hack。【参考方案3】:

您可以尝试添加显式类型属性来控制结构对齐:

typedef struct
    char        t1;
    long long   t2;
    char        t3;
 struct_size_test __attribute__ ((aligned (8))); // aligned(8) = 8-byte alignment

【讨论】:

感谢您的快速建议,但它仍然显示 sizeof(struct_size_test)==[16]。很奇怪! 我认为对齐属性应该属于各个成员。 @tangrs 哦,太好了!我刚看到这个。您是对的,对齐属性应该属于各个成员。谢谢您的帮助!你知道为什么'-malign-double'标志不起作用吗? 可能是 GCC 特有的标志 @tangrs 好的!还是谢谢!

以上是关于结构填充编译标志的主要内容,如果未能解决你的问题,请参考以下文章

编译时检查以确保结构中的任何地方都没有填充

图形填充之边标志算法

忽略符号的 C 编译器标志

Visual Studio中的c ++编译器标志

如果我布置结构的字段以便它们不需要任何填充,那么符合标准的 C++ 编译器可以添加额外的东西吗?

如何避免结构填充?