Python struct.pack() behavior


data = 5 
Result1 = struct.pack("<L", data)
  1. 整数数据被转换为长(64位)。那是 01000000 00010100 00000000 00000000 00000000 00000000 00000000 00000000
  2. 然后将钻头逆转为字节,并将其存储在Result1中,为字节字符串?那是 00000000 00000000 00000000 00000000 00000000 00000000 00010100 01000000

这是该代码到底发生了什么,还是我误解了任何东西?

来自[python 2.docs]:struct-将字节解释为包装的二进制数据:

此模块在Python值和表示为Python字符串的C结构之间执行转换。

这意味着它将以 char 序列打印参数的内存表示。内存(以及驻留在其中的所有内容)都是字节序列。每个字节都有一个值 [0..255] (为了简单起见,我使用 nosigned )。
因此,当它代表一个字节时,它将首先搜索 char 具有与字节值匹配的 ascii 代码,如果这样的a()找到可打印的 char ,它将是该字节的表示,否则表示为字节值(in hex )之前为 x (表示非可打印 char s的约定)。旁注,(非扩展) ascii char s具有 0 128 的值。。。>

示例:

  • > 65 的字节值( hex 0x41 )将表示为' a '( a 's ascii 代码是 65

  • > 217 的字节值将简单地表示为' xd9 '(此 ascii 代码没有可打印 char

在进一步发展之前,需要几个单词 endianness :这就是计算机存储器中数据(数字)表示的方式。几个链接(尽管可以在互联网上找到许多资源):

  • [Wikipedia]:endianness
  • [umd.cs]:大和小恩迪安

我将尝试简要解释 big Little Endian (再次,为简单起见,我会坚持使用 8位原子仅元素大小)。

想象我们正在在纸上进行一些内存表示练习,或者更好:在黑板上。如果我们将黑板表示为计算机存储(当我们到达右边缘时,也下面是下一行)。
我们要表示数字 0x12345678 作为a 4 节号,从左上角开始(每个字节都由恰好 2 hex 数字组成):

╔═══════════╦══════════╦══════════╦══════════╦══════════╗
║   Byte    ║    01    ║    02    ║    03    ║    04    ║
╠═══════════╬══════════╬══════════╬══════════╬══════════╣
║   Value   ║   0x12   ║   0x34   ║   0x56   ║   0x78   ║
╚═══════════╩══════════╩══════════╩══════════╩══════════╝

我们的编号最重要的字节存储在最低内存地址(和最少)重要的字节存储在最高),即 big endian 。对于 Little Endian ,我们的数字字节以相反的顺序。

作为一个结论,人类认为" 大末日 ly"。

我要涵盖的另一个主题是: types int 更精确)。 python ,基于 c ,继承其本地类型,因此 int 将具有 4 bytes(在某些平台上/架构可能具有 8 )。因此, int (再次,谈论 unsigned )具有一个值 [0..4294967295] 。但是,即使以较小的值: 5 例如(仅需要 1 字节),它仍然会占据 4 bytes:)未使用的字节将用 0 s填充。因此,我们的编号为A 4 byte unsigned int 将为( hex ): 0x0000000005

现在,回到我们的问题(S):如上所述, 5 is 0x05 (或 0x00000005 - 4 4 byte unsigned int )或 chars :" x00 x00 x00 x00 x05 "。但这比 struct.pack 显示的顺序相反。我认为您已经猜到了原因:它在 Little Endian 表示中。这是由1 st fmt )参数(" &lt; )的零件给出[Python 2.docs]:struct。 pack fmt,v1,v2,... )(可能的值在同一页面上列出:[Python 2:.docs]:struct-字节顺序,大小和对齐)。对于 55555 ,情况是相同的。它的 hex 表示是: 0xD903 0x000000D903

如果尚无意义,请通过输入 data_set 的不同值并参见输出:

,以使用代码的此略微修改的版本并使用它。

code.py

import struct
fmt = "<L"
data_set = [5, 55555, 0x12345678]
for data in data_set:
    output_str = "{} - {}".format(hex(data), repr(struct.pack(fmt, data)).strip("'"))  # This is just for formatting output string to be displayed to the user
    print(output_str)  # Python3 compatible (however the formatting above won't behave nicely)

输出

c:WorkDevStackOverflowq037990060>"C:Installx64HPEOPSWpython2.7.10__00python.exe" "code.py"
0x5 - x05x00x00x00
0xd903 - x03xd9x00x00
0x12345678 - xV4x12

最新更新