我为自定义网络协议设计了一个Packet结构,如下所示:
typedef struct {
uint8_t src;
uint8_t dest;
uint8_t len;
uint8_t flag;
//bitfields allocated R-L? gcc is somehow merging the fields also?
uint8_t type :4;
uint16_t seq :12; // 12 bits used for this field.[F3|02] == 0x02F3 on litle endian?
uint8_t checksum;
}Packet;
根据我对位字段和结构填充的理解,每个字段都将存储在连续的字节中(seq将从一个新的字节边界开始)。没有尾随填充,因为我的设备也是x64。
以图形方式:|src|dest|len|flag|type| seq |checksum|
64位头,无结构填充。
为了测试我的数据包以进行进一步的序列化,我通过以下方式初始化了一个数据包:
thispack.src = 0x07;
thispack.dest = 0x34;
thispack.len = 0x5F;
thispack.flag = 0xA2;
thispack.type = 0x05;
thispack.seq = 0xAED;
thispack.checksum= 0x23;
我正在运行一个小字节序系统。我希望结构体的内存布局是:0x07 0x34 0x5F 0xA2 0x05 0xED 0x0A 0x23
,其中seq的字节由little-endian规则反转。
但是,在gdb中运行x/8bx &thispack
将返回以下内容:0x07 0x34 0x5f 0xa2 0xd5 0xae 0x23 0x00
我不明白0xD 5和0xAE是如何获得的。这会导致通过.
表示法访问结构体字段时的不确定性:
以下是我认为正确的:
uint8_t mytype = thispack.type
应将0x05
存储在mytype
引用的字节中。uint16_t myseq = thispack.seq
应该将0xED 0x0A
存储在分配给myseq的2个字节中。
我看不出还有什么别的原因。
1条答案
按热度按时间tf7tbtn21#
好的。在这种情况下,我的设备上的gcc会打包位域吗?
有:
结果https://godbolt.org/z/1Teh7Er9f:
是否有其他原因导致记忆没有按照我预期的顺序排列?
不,你需要使用一个小的变通方法:
结果https://godbolt.org/z/1MGPYsW1W: