为什么Python struct.pack中的混合类型使用的空间比需要的多?

时间:2014-01-24 12:39:07

标签: python pack

我刚刚尝试在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

4 个答案:

答案 0 :(得分:8)

struct.pack通常用于访问内存结构,而不是文件。在内存中,访问在奇数/未对齐地址占用多个字节的数据可能会导致异常或性能损失。

这就是为什么编译器对齐数据(通常在4或8字节边界上)和Python中的the struct module也是如此。

要禁用此功能,可以使用格式字符串的第一个字符来设置字节顺序和对齐方式。在您的情况下,请尝试struct.pack("=bi",1,1)

如果您没有指定任何内容,则隐式@表示“本机字节顺序,大小和对齐”。 See the documentation for other options

答案 1 :(得分:4)

Yes, it is.

  

默认情况下,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的顺序,则不应出现问题。