通过套接字 C++ 发送时位域值发生变化
Bitfield value changes when sent over socket C++
我有一个如下所示的位域:
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
已设置(可通过在发送前打印值来验证)但接收方不会看到 [=13] =] 已设置。传输代码如下:
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
在发送方将其设置为 1 时为 0。为什么会发生这种情况?编译器可能会为发送方和接收方插入不同的填充吗?我需要担心单位值的字节顺序吗?
编译器可以根据需要布置位域。如果愿意,它可以在每次执行时将它们随机化。绝对没有禁止这样做的规则。如果您想以可依赖的可预测二进制格式序列化数据,请编写执行此操作的代码。
唯一的例外是,如果您的编译器对打包结构有一些特定的保证,并且您愿意将自己限制在该编译器上。您没有指定您正在使用的编译器,但我怀疑它确实如此。
真的没有理由写这样的代码。您想编写保证按照相关标准工作的代码,而不是在没有任何事情打破它所做的假设的情况下可能碰巧工作的代码。
我有一个如下所示的位域:
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
已设置(可通过在发送前打印值来验证)但接收方不会看到 [=13] =] 已设置。传输代码如下:
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
在发送方将其设置为 1 时为 0。为什么会发生这种情况?编译器可能会为发送方和接收方插入不同的填充吗?我需要担心单位值的字节顺序吗?
编译器可以根据需要布置位域。如果愿意,它可以在每次执行时将它们随机化。绝对没有禁止这样做的规则。如果您想以可依赖的可预测二进制格式序列化数据,请编写执行此操作的代码。
唯一的例外是,如果您的编译器对打包结构有一些特定的保证,并且您愿意将自己限制在该编译器上。您没有指定您正在使用的编译器,但我怀疑它确实如此。
真的没有理由写这样的代码。您想编写保证按照相关标准工作的代码,而不是在没有任何事情打破它所做的假设的情况下可能碰巧工作的代码。