Python Struct模块行为异常

6 投票
4 回答
1313 浏览
提问于 2025-04-17 11:58

我在使用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呢?

4 个回答

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.
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'))
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

示例:http://ideone.com/EMlgm

撰写回答