【问题标题】:Endianness of integers in PythonPython中整数的字节顺序
【发布时间】:2010-11-26 20:47:49
【问题描述】:

我正在开发一个程序,我将一些数据存储在整数中并按位处理。例如,我可能会收到数字 48,我将逐位处理它。一般来说,整数的字节顺序取决于整数的机器表示,但是 Python 是否会做任何事情来保证整数始终是小字节序?还是我需要像在 C 中一样检查字节顺序,然后为这两种情况编写单独的代码?

我问是因为我的代码在 Sun 机器上运行,虽然它现在运行的机器使用 Intel 处理器,但我将来可能不得不切换到具有 Sun 处理器的机器,我知道这是 big-endian。

【问题讨论】:

    标签: python integer endianness


    【解决方案1】:

    Python 的 int 与运行它的处理器具有相同的字节顺序。 struct 模块允许您以本机、小端或大端方式将字节 blob 转换为整数(反之亦然,以及其他一些数据类型),具体取决于您选择的 format string@ 或没有字节序字符以使用本机字节序(以及本机大小 - 其他所有内容都使用标准大小),'~' 用于本地,'' 或'!'对于大端。

    这是逐字节的,不是逐位的;不确定在这种情况下逐位处理的确切含义,但我认为它可以类似地适应。

    对于简单情况下的快速“批量”处理,还可以考虑array 模块——fromstringtostring 方法可以快速处理大量字节,byteswap 方法可以为您提供“其他”字节序(本地到非本地,反之亦然),同样快速且适用于大量项目(整个数组)。

    【讨论】:

    • 即使在小端系统上,python 似乎也总是大端。例如:打印 0x0001 将打印 1
    • @David天宇王,你从你的观察中得出了完全没有根据的推论——0x0001只是整数1的一个奇怪的冗余十六进制表示法,与内部表示无关!
    • 是的,谢谢,我把这一切搞混了。它似乎只是一个整数的 HEXSTRING。
    • 那么二进制符号呢? 0b10000001101 这会在所有系统和 Python 版本上给出数字 1037 吗?
    • @NiklasR 是的。 The specification 没有明确提到字节序,但它确实清楚地表明二进制文字与任何其他整数文字的工作方式相同,并且它产生一个具有给定 value 的对象,而不是给定的表示.
    【解决方案2】:

    如果您需要“按位”处理数据,那么bitstring 模块可能会对您有所帮助。它还可以处理平台之间的字节序。

    struct module 是处理平台间字节序的最佳标准方法。例如,这使用原生字节序将整数 1、2、3 打包并解包为两个“shorts”和一个“long”(在大多数平台上为 2 和 4 个字节):

    >>> from struct import *
    >>> pack('hhl', 1, 2, 3)
    '\x00\x01\x00\x02\x00\x00\x00\x03'
    >>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
    (1, 2, 3)
    

    要以编程方式检查平台的字节序,您可以使用

    >>> import sys
    >>> sys.byteorder
    

    这将返回"big""little"

    【讨论】:

    • 我见过很多这样的解释(对于 sys.byteorder 也是 cudo,不知道),但我不得不问。假设我有一些未知文件要读取,我如何知道某些 const 字符是短还是长和/或大端和小端?
    • @Danilo:一般来说你无法分辨。要对未知文件格式进行逆向工程,您可以查看数据并猜测哪种大小/字节序最有意义。为了说明,如果你用错误的字节序打开我的例子,你得到 (256, 512, 50331648) 而不是 (1, 2, 3) 这是一个合理的线索,你弄错了......
    【解决方案3】:

    什么时候检查?

    进行按位运算时, int in 将与您输入的 int 具有相同的字节序。您无需检查。您只需要在两种语言的字节序列之间转换时关心这一点,afaik。

    在 Python 中,您为此使用 struct 模块,最常见的是 struct.pack() 和 struct.unpack()。

    【讨论】:

    • 这很重要,因为我在我的代码中做这样的事情: if (a >> 2 & 1) ... elif (b >> 3 & 1) ... 但在 bigendian 上我会必须写 if (a
    • @Gordon:我认为这不对。字节顺序大字节序和小字节序和位大小字节序之间是否存在一些混淆?如果a 是一个整数,那么您可能不必担心它的字节顺序,这只是您如何从原始字节数据创建它的问题。
    • @Gordon:不,你不会。 Big/small-endian 不会改变位的顺序,而是 bytes 的顺序。移位操作在 Python 和 C 中处理这个问题(因为它们实际上都使用处理器移位操作)。
    【解决方案4】:

    下面的sn-p会告诉你你的系统默认是不是little endian(否则就是big-endian)

    import struct
    little_endian = (struct.unpack('<I', struct.pack('=I', 1))[0] == 1)
    

    但是请注意,这不会影响位运算符的行为:1&lt;&lt;1 等于 2,无论您的系统的默认字节顺序如何。

    【讨论】:

      猜你喜欢
      • 2013-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2010-11-14
      • 1970-01-01
      • 2016-10-18
      相关资源
      最近更新 更多