我有一个如下所示的位域:
typedef struct __attribute__((__packed__)) MyStruct {
unsigned int val1:14;
unsigned int val2:1;
unsigned int val3:1;
unsigned int val4:1;
unsigned int val5:1;
unsigned short aFullShort;
unsigned int aFullInt;
} MyStruct;
我通过网络发送这些值,并注意到有时发件人会认为val1
已设置(可通过在发送之前打印值来验证),但接收方将看不到val1
已设定。传输代码如下:
MyStruct* myStruct = new MyStruct(); //initialize fields here
sendto(sock, myStruct, sizeof(MyStruct), 0, ...);
阅读代码如下:
unsigned char theBuffer[sizeof(MyStruct)];
recvfrom(aSocket, &theBuffer, sizeof(theBuffer), 0, ...);
从套接字读取字节后,我重新解释将字节转换为MyStruct
并执行aFullShort
和aFullInt
的字节序转换。发生损坏时,接收方认为val1
为0时,发送方将其设置为1.为什么会发生这种情况?编译器可能会为发送方和接收方插入不同的填充吗?我是否需要担心单个位值的字节序?
答案 0 :(得分:2)
编译器可以根据需要布置位字段。如果需要,它可以在每次执行时随机化它们。绝对没有规定禁止这一点。如果要以可依赖的可预测二进制格式序列化数据,请编写执行此操作的代码。
唯一的例外是,如果您的编译器对打包的结构有一些指定的保证,并且您愿意仅限于该编译器。你没有指定你正在使用的编译器,但我怀疑它确实如此。
没有理由编写这样的代码。您希望编写保证按相关标准工作的代码,而不是在没有任何事情发生的情况下可能会起作用的代码。