【发布时间】:2015-07-10 20:32:29
【问题描述】:
类似的问题,但特定于打包结构: Why would the size of a packed structure be different on Linux and Windows when using gcc?
我正在为需要通过网络连接处理结构良好的数据的 Linux 和 Windows 构建一个共享库。我在 Linux 上使用 gcc 4.8.2,并使用 i686-pc-mingw32-gcc 4.8.1 交叉编译 Windows 目标。
我制作了这个小程序来演示这个问题(注意 GCC 属性已被注释掉,留作参考):
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef uint16_t word_t;
typedef enum //__attribute__((__packed__))
{
PRIO_0 = 0,
PRIO_1,
PRIO_2,
PRIO_3,
PRIO_4,
PRIO_5,
PRIO_6,
PRIO_7,
}
prio_t;
typedef enum //__attribute__((__packed__))
{
FLAG_A = 0,
FLAG_B,
}
flag_t;
typedef struct //__attribute__((__packed__))
{
word_t id : 8;
prio_t prio : 3;
flag_t flag_1 : 1;
flag_t flag_2 : 1;
flag_t flag_3 : 1;
flag_t flag_4 : 1;
word_t spare : 1;
}
recd_t;
int main(int argc, char *argv[])
{
#define NAME_WIDTH 32
printf("%-*s = %lu\n", NAME_WIDTH, "sizeof(prio_t)", (unsigned long)sizeof(prio_t));
printf("%-*s = %lu\n", NAME_WIDTH, "sizeof(flag_t)", (unsigned long)sizeof(flag_t));
printf("%-*s = %lu\n", NAME_WIDTH, "sizeof(recd_t)", (unsigned long)sizeof(recd_t));
return 0;
}
我正在为 Linux 编译使用:
gcc -g -Wall test.c -o ./test
和 Windows:
i686-pc-mingw32-gcc -g -Wall test.c -o ./test.exe
我认为非常简单。在 Linux 上运行时,输出是我所期望的:
sizeof(prio_t) = 4
sizeof(flag_t) = 4
sizeof(recd_t) = 4
但在 Windows 上:
sizeof(prio_t) = 4
sizeof(flag_t) = 4
sizeof(recd_t) = 12
那么,Windows 尺寸有什么问题呢?为什么在这种情况下它们与 Linux 不同?
我最终需要打包这些枚举和结构,但这个问题会在打包完成之前出现。但启用后,结果相似:
Linux:
sizeof(prio_t) = 1
sizeof(flag_t) = 1
sizeof(recd_t) = 2
窗户:
sizeof(prio_t) = 1
sizeof(flag_t) = 1
sizeof(recd_t) = 6
【问题讨论】:
-
如果你真的想要“通过网络连接结构良好的数据”,我的建议是不尝试使用打包结构来实现。我知道这就是它们的用途,但是让它工作起来可能非常困难,而且你仍然无法解决字节顺序问题。请参阅this question 的进一步讨论。
-
为什么是
uint16_t word_t;而不是uint8_t word_t;? -
@SteveSummit 感谢您的链接。不确定您是否假设与字节序注释进行 IP 通信,但它很可能会使用 ARINC 429。不希望网络详细信息影响问题
-
@alk 外部接口定义。不是我的选择:)
-
如果您有任何可移植的想法:(1) 不要使用位域,(2) 参见 1,(3) 序列化数据而不是使用打包结构。
标签: c windows gcc struct bit-fields