通过套接字C ++发送时,位域值会发生变化

时间:2017-10-31 18:39:18

标签: c++ sockets bit-fields

我有一个如下所示的位域:

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并执行aFullShortaFullInt的字节序转换。发生损坏时,接收方认为val1为0时,发送方将其设置为1.为什么会发生这种情况?编译器可能会为发送方和接收方插入不同的填充吗?我是否需要担心单个位值的字节序?

1 个答案:

答案 0 :(得分:2)

编译器可以根据需要布置位字段。如果需要,它可以在每次执行时随机化它们。绝对没有规定禁止这一点。如果要以可依赖的可预测二进制格式序列化数据,请编写执行此操作的代码。

唯一的例外是,如果您的编译器对打包的结构有一些指定的保证,并且您愿意仅限于该编译器。你没有指定你正在使用的编译器,但我怀疑它确实如此。

没有理由编写这样的代码。您希望编写保证按相关标准工作的代码,而不是在没有任何事情发生的情况下可能会起作用的代码。