简体   繁体   English

long 的结构长度取决于字节顺序?

[英]Struct length of long depending on byte order?

I want to use struct.unpack() to get a long value from a byte string in Python 2.7, but I found some strange behaviour and I would like to know if this is a bug or not, and also, what I can do to get around it.我想使用struct.unpack()从 Python 2.7 中的字节字符串中获取长值,但我发现了一些奇怪的行为,我想知道这是否是一个错误,以及我能做些什么绕过它。

What happens is the following:发生的情况如下:

import struct
>>> struct.unpack("L","")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 8

This is the expected behaviour.这是预期的行为。 It wants an 8-byte string to extract the 8-byte long value.它需要一个 8 字节的字符串来提取 8 字节长的值。

Now I change the byte order to network byte order and I get the following:现在我将字节顺序更改为网络字节顺序,我得到以下信息:

>>> struct.unpack("!L","")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 4

Suddenly it only wants 4 bytes for the 8-byte long value.突然间它只需要 4 个字节作为 8 字节长的值。

What is up with that, and what can I do to get around this?这是怎么回事,我能做些什么来解决这个问题?

The issue here is that struct is using your machine's native long size in the first case, and struct 's "standard" long size in the second.这里的问题是struct正在使用您的计算机的本地long在第一种情况下大小和struct的‘标准’ long尺寸在第二位。

In the first example, you don't specify a byte-order, size, and alignment specifier (one of @=<>! ) so struct assumes '@' , which uses your machine's native values, namely your machine's native long size.在第一个示例中,您没有指定字节顺序、大小和对齐说明符@=<>! ),因此struct假定'@' ,它使用您机器的本机值,即您机器的本long尺寸。 In order to be consistent across platforms,struct defines standard sizes for each type , which may differ from your machine's native sizes.为了跨平台保持一致,struct为每个 type 定义了标准大小,这可能与您机器的本机大小不同。 Every specifier except for '@' uses these standard sizes.除了'@'之外的每个说明符都使用这些标准大小。

So, in the case of long , struct 's standard is 4 bytes, which is why '!L' (or any '[=<>!]L' expects 4 bytes. However, your machine's native long is apparently 8 bytes, which is why '@L' or 'L' expects 8. If you want to use your machine's native byte-order, but still be compatible with struct 's standard sizes, I would recommend that you specify all formats with '=' , instead of letting Python default it to '@' .因此,在long的情况下, struct的标准是 4 个字节,这就是为什么'!L' (或任何'[=<>!]L'需要 4 个字节。但是,您机器的本机long显然是 8 个字节,这就是为什么'@L''L'需要 8。如果您想使用机器的本机字节顺序,但仍然与struct的标准大小兼容,我建议您使用'='指定所有格式,而不是让 Python 默认为'@'


You can check the size expectation with struct.calcsize , ie:您可以使用struct.calcsize检查大小期望,即:

>>> struct.calcsize('@L'), struct.calcsize('=L')

(this returns (4, 4) on my 64-bit Windows 10 machine, but (8, 4) on my 64-bit Ubuntu 16.04 machine.) (这在我的 64 位 Windows 10 机器上返回(4, 4) ,但在我的 64 位 Ubuntu 16.04 机器上返回(8, 4) 。)

You can also directly check your machine's type size by compiling a C script to check the value of sizeof(long) , for example:您还可以通过编译C脚本来检查sizeof(long)的值,直接检查您机器的类型大小,例如:

#include <stdio.h>

int main()
{
    printf("%li",sizeof(long));
    return 0;
}

I followed this guide to compile the C script on my Windows 10 machine.我按照本指南在我的 Windows 10 机器上编译C脚本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM