我刚刚尝试在Python中使用struct.pack,当我混合类型时我不理解它的行为
当我试图打包一个字符而不是其他字符时,它按预期工作,即
struct.pack("b",1)
给出'\x01'
。但是,只要我尝试混合使用不同类型的数据,就会将字符填充为与此类型一样长,例如
struct.pack("bi",1,1)
给出'\x01\x00\x00\x00\x01\x00\x00\x00'
。
这是标准行为,为什么?有办法吗?
修改
更简单地说:
>>> struct.calcsize("b")
1
>>> struct.calcsize("i")
4
>>> struct.calcsize("bi")
8
答案 0 :(得分:8)
struct.pack
通常用于访问内存结构,而不是文件。在内存中,访问在奇数/未对齐地址占用多个字节的数据可能会导致异常或性能损失。
这就是为什么编译器对齐数据(通常在4或8字节边界上)和Python中的the struct
module也是如此。
要禁用此功能,可以使用格式字符串的第一个字符来设置字节顺序和对齐方式。在您的情况下,请尝试struct.pack("=bi",1,1)
如果您没有指定任何内容,则隐式@
表示“本机字节顺序,大小和对齐”。 See the documentation for other options
答案 1 :(得分:4)
默认情况下,C类型以机器的本机格式和字节顺序表示,并在必要时通过跳过填充字节进行正确对齐(根据C编译器使用的规则)。
如果您不想进行对齐,只需使用'='
,'<'
或'>'
(与'!'
相同)启动格式字符串即可指定字节顺序。
答案 2 :(得分:2)
来自manual:
默认情况下,打包给定C结构的结果包括填充字节,以便维护所涉及的C类型的正确对齐;类似地,在拆包时考虑对齐。选择此行为是为了使压缩结构的字节与相应C结构的内存中的布局完全对应。
i
是一个4字节的整数,将放在它自己的字上。因此,它旁边的任何内容都不会填充单词,将填充它。您可以通过指定没有原生对齐的byte order来覆盖此行为。
这就是为什么 - 更复杂的结构 - 内部事物的排序很重要。
另请参阅有关该主题的Wikipedia article。
答案 3 :(得分:2)
见the documentation for struct;特别是它说
默认情况下,打包给定C结构的结果包括填充字节,以便维护所涉及的C类型的正确对齐;类似地,在拆包时考虑对齐。选择此行为是为了使压缩结构的字节与相应C结构的内存中的布局完全对应。
并查看例如这个用于C结构内存布局的Stack Overflow问题:C struct memory layout?
简而言之,整数是4个字节,因此它必须从4的倍数开始。如果改变b和i的顺序,则不应出现问题。