Python结构模块的行为很奇怪

6
我正在使用struct模块,但事情并不像我预期的那样进行。我肯定是对这个模块有些误解。
import struct
s = struct.Struct('Q');
print s.size
s = struct.Struct('H L Q');
print s.size
s = struct.Struct('H I Q');
print s.size
s = struct.Struct('H I Q H');
print s.size

这的输出结果为:
8
24
16
18

我这里漏掉了什么?为什么第二个和第三个不同大小,而第四个不是16?


您正在使用本地格式,这意味着大小和填充取决于您的平台。如果您想使用没有填充的标准大小,请在格式字符串前加上=,<,>,或! - Cat Plus Plus
1
对齐方式出了问题。为什么我会认为 Python 与我的紧凑结构一样呢?谢谢大家。 - mdogg
4个回答

7

对齐问题。

假设您在一个64位的非Windows平台上运行:Q和L将是8字节长,I是4字节,H是2字节。

这些类型必须放置在其大小的倍数的位置上,以获得最佳效率。

因此,第二个结构体将被排列为:

HH______ LLLLLLLL QQQQQQQQ

第三个结构体:
HH__IIII QQQQQQQQ

第四个结构体:

HH__IIII QQQQQQQQ HH

如果您不需要对齐,并且需要 L 具有 4 字节(即“标准”大小),则需要使用 =>< 格式进行格式化,如 http://docs.python.org/library/struct.html#struct-alignment 中所述:

import struct
s = struct.Struct('=Q')
print s.size
s = struct.Struct('=HLQ')
print s.size
s = struct.Struct('=HIQ')
print s.size
s = struct.Struct('=HIQH')
print s.size

Demo: http://ideone.com/EMlgm


4
如果您查看struct的文档

或者,格式字符串的第一个字符可以用于指示按照以下表格中的字节顺序、大小和对齐方式打包数据:

Character Byte order             Size       Alignment
@         native                 native     native
=         native                 standard   none
<         little-endian          standard   none
>         big-endian             standard   none
!         network (= big-endian) standard   none

如果第一个字符不是这些字符之一,则假定为“@”。

由于您没有给出任何大小提示,选择了native大小和对齐方式,这可能会由于对齐和不同的大小而给出不可预测的大小。这应该可以解决问题:

import struct
print(struct.calcsize('!Q'))
print(struct.calcsize('!H L Q'))
print(struct.calcsize('!H I Q'))
print(struct.calcsize('!H I Q H'))

太棒了。我正在解包一个打包的C结构体。在这种情况下,我应该使用<而不是!,对吗? - mdogg
1
@mdogg:不,如果你解包(unpack)的东西是确定为小端序(little-endian),那么使用 < 是正确的,否则应该使用 = - orlp
@mdogg:使用<还是>取决于您正在解包的紧凑C结构中数据的字节顺序,也就是端序。 - martineau

1
如果您使用的是64位架构,则int为4个字节,long为8个字节:
>>> struct.Struct('I').size
4
>>> struct.Struct('L').size
8

对于最后一个,这就是我们所谓的“对齐”:http://docs.python.org/library/struct.html#struct-alignment
>>> struct.Struct('I').size
4
>>> struct.Struct('H').size
2
>>> struct.Struct('HI').size
8
# => aligned to the next word.

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接