为什么第一个打包数据在struct little endian中,而其余的是big endian?

问题描述 投票:2回答:2
import struct
port = 1331
fragments = [1,2,3,4]
flags = bytes([64])
name = "Hello World"

data = struct.pack('HcHH', port, flags, len(fragments), len(name))

print(int.from_bytes(data[3:5], byteorder='big'))
print(int.from_bytes(data[5:7], byteorder='big'))
print(int.from_bytes(data[0:2], byteorder='little'))

当我像这样打印它们时,它们会正确地出来。似乎端口使用小尾数,而len(fragments)len(name)使用大尾数。如果我还在端口上进行大端字节排序,则它将得到错误的值。

那么为什么结构会如此表现?还是我错过了什么?

python python-3.x struct endianness
2个回答
1
投票
>>> struct.calcsize('HcHH') 8 >>> struct.calcsize('HHHc') 7

因此您的数据与您所想的不一致。正确的拆包是:

print(int.from_bytes(data[4:6], byteorder='little'))
# 4
print(int.from_bytes(data[6:], byteorder='little'))
# 11

事实证明,偶然地,'c'的添加字节为'\ x00',并使您的字节链在big-endian中正确:

>>> data
b'3\x05@\x00\x04\x00\x0b\x00'
        ^^^^
        this is the intruder

0
投票
pack

结果看起来像这样(打印有struct.pack('@HcHH', port, flags, len(fragments), len(name))

'.'.join(f'{x:02X} for x in data')

数字4用小尾数编码在字节4和5中,而11编码在字节6和7中。字节3是一个填充字节,由33.05.40.00.04.00.0B.00 0 1 2 3 4 5 6 7 插入以适当地将后面的pack对齐到均匀边界。

short

注默认情况下,打包给定C结构的结果包括填充字节,以维护所涉及C类型的正确对齐;同样,拆箱时也要考虑对齐方式。选择此行为是为了使打包结构的字节与对应的C结构的内存中的布局完全对应。要处理平台无关的数据格式或忽略隐式填充字节,请使用docs大小和对齐方式,而不是standard大小和对齐方式:有关详细信息,请参见native

要删除对齐字节并证明您对字节位置的假设,同时保持本机字节顺序,请使用

Byte Order, Size, and Alignment

您还可以通过使用struct.pack('=HcHH', port, flags, len(fragments), len(name)) <作为前缀来使用固定字节顺序。

© www.soinside.com 2019 - 2024. All rights reserved.