我有一个看起来像这样的结构
struct message_header
{
unsigned long msg_num : 32; //0-3 message id
unsigned long msg_len : 32; //4-7 message length
unsigned long hardware_version : 16; //8-9 hardware version
unsigned long sender_location : 32 //10-13 location
unsigned long message; //14 ... messages
};
message_header * msg_ptr;
从recvbuf
函数接收到字符数组(recvfrom
)后,我会这样做
reinterpret_cast
,
msg_ptr = reinterpret_cast<message_header*>(recvbuf)
然而,在我的模拟器(来自linux,VM)发送数据和我的接收器(结构在接收器中)(在Windows上)之后,输出数据不符合。
假设从模拟器发送的数据是:
msg num : 1010
msg len : 20
hardware version: 1
location: 25
messages: //rest of the bytes
来自wireshark的数据包显示:
00 00 03 F2
00 00 00 14
00 01 00 00
00 19 00 00
...
输出打印是:
msg num : 1010
msg len : 20
hardware version: 1
location: 1638400
经过多次调试后,我注意到在演员表中,在硬件版本之后,00 00
之后的01
被丢弃或被跳过,我不知道哪一个我找不到确定它的方法,00 19 00 00
的接下来的4个字节被投射到我的sender_location
。
发件人的所有邮件类型和长度都是根据发件人的设计规范构建的,发件人的hardware version
是unsigned short
。
我已阅读以下问题和答案
Fields in a struct skipping bytes
我试过但无济于事,请指教。
答案 0 :(得分:0)
成员的对齐将位于边界上,该边界是n的倍数或成员大小的倍数,以较小者为准。
我一开始并不明白这意味着什么,直到我一遍又一遍地重读,我才意识到我的hardware version
正在使用long
4 bytes
,而不是我应该使用short
2 bytes
来代替另一个问题,这就是为什么位域限制不起作用,或者我可能错误地理解它。
因此,在将其从long
更改为short
以及使用#pragma pack(1)
后,该广告系列现在运行正常。
我发现的方法是使用offsetof
函数来检查
cout << offsetof (message_header, msg_num) << endl;
cout << offsetof (message_header, msg_len) << endl;
cout << offsetof (message_header, hardware_version) << endl;
cout << offsetof (message_header, sender_location ) << endl;
cout << offsetof (message_header, message) << endl;
打印输出,然后我意识到位域根本不起作用。
0
4
8
12
16
更改hardware_version
后,从long
更改为short
,而没有#pragma pack(1)
,打印输出仍然与上面的相似,但是,#pragma pack(1)
已启用,打印输出
0
4
6
10
14