/ / Długość Struct w zależności od kolejności bajtów? - python, python-2.7, struct

Długość struktury długiej w zależności od kolejności bajtów? - python, python-2.7, struct

Chcę użyć struct.unpack() aby uzyskać długą wartość z ciągu bajtów w Pythonie 2.7, ale znalazłem jakieś dziwne zachowanie i chciałbym wiedzieć, czy jest to błąd, czy nie, a także, co mogę zrobić, aby go obejść.

Co się dzieje, jest następujące:

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

To jest oczekiwane zachowanie. Chce 8-bajtowy ciąg do wyodrębnienia 8-bajtowej wartości.

Teraz zmieniam kolejność bajtów na kolejność bajtów sieciowych i otrzymuję następujące informacje:

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

Nagle potrzebuje tylko 4 bajtów dla 8-bajtowej wartości.

Co się z tym dzieje i co mogę zrobić, aby obejść to?

Odpowiedzi:

1 dla odpowiedzi № 1

Chodzi o to, że struct używa rodzimego komputera long rozmiar w pierwszym przypadku, i struct„s” standard long rozmiar w drugim.

W pierwszym przykładzie nie określasz a kolejność bajtów, rozmiar i specyfikator wyrównania (jeden z @=<>!) więc struct zakłada "@", który używa wartości rodzimych komputera, a mianowicie rodzimego komputera long rozmiar. Aby być spójnym na różnych platformach, struct definiuje standardowe rozmiary dla każdego typu, które mogą różnić się od rodzimych rozmiarów twojej maszyny. Każdy specyfikator z wyjątkiem "@" używa tych standardowych rozmiarów.

Tak więc w przypadku long, struct„Standard ma 4 bajty, dlatego "!L" (lub dowolny "[=<>!]L" oczekuje 4 bajtów. Jednak natywna maszyna long najwyraźniej 8 bajtów, dlatego "@L" lub "L" oczekuje 8. Jeśli chcesz korzystać z rodzimej kolejności bajtów komputera, ale nadal być kompatybilny struct„Standardowe rozmiary, polecam określenie wszystkich formatów za pomocą "=", zamiast pozwolić Pythonowi na domyślne ustawienie "@".


Możesz sprawdzić oczekiwany rozmiar struct.calcsize, tj .:

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

(to wraca (4, 4) na moim 64-bitowym komputerze z systemem Windows 10, ale (8, 4) na moim 64-bitowym komputerze Ubuntu 16.04.)

Możesz również bezpośrednio sprawdzić rozmiar swojego komputera, kompilując a C skrypt do sprawdzenia wartości sizeof(long), na przykład:

#include <stdio.h>

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

podążałem ten przewodnik skompilować C skrypt na moim komputerze z systemem Windows 10.