Python struct.pack() поведение

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

это именно то, что происходит с этим кодом или я что-то не так понял?

1 ответ

Из [Python 2]: struct - интерпретировать байты как упакованные двоичные данные:

Этот модуль выполняет преобразования между значениями Python и структурами C, представленными в виде строк Python.

Это означает, что он напечатает представление аргумента (ов) в памяти в виде последовательности символов. Память (и все, что в ней находится) представляет собой последовательность байтов. Каждый байт имеет значение [0..255] (для простоты я использую unsigned).
Поэтому, когда он будет представлять байт, он сначала будет искать символ, имеющий код ASCII, соответствующий значению байта, и, если будет найден такой (печатный) символ, это будет представление этого байта, в противном случае представление будет значение байта (в шестнадцатеричном формате), которому предшествует \x (соглашение для представления непечатаемых символов). В качестве примечания, (не расширенные) символы ASCII имеют значения от 0 до 128.

Пример:

  • Значение байта 65шестнадцатеричном формате 0x41) будет представлено как " A " (так как код A ASCII A равен 65)

  • Значение байта 217 (hex 0xd9) будет просто представлено как ' \ xd9 ' (для этого ASCII- кода нет печатного символа)

Прежде чем идти дальше, нужно сказать несколько слов о порядке байтов: именно так данные (в нашем случае цифры) представляются в памяти компьютера. Пара ссылок:

Я попытаюсь кратко объяснить разницу между старшим и младшим порядком байтов (опять же, для простоты, я буду придерживаться только 8-битного размера атомного элемента).

Представьте, что мы выполняем некоторые упражнения по отображению памяти на листе бумаги или, что лучше, на доске. Если бы мы представляли доску как память компьютера, то верхний левый угол был бы ее началом (адрес 0), и адреса увеличивались бы по мере того, как мы идем вправо (а также вниз ниже к следующей строке, когда мы достигаем правой стороны). края).
Мы хотим представить число 0x12345678 как 4- байтовое число, начиная с верхнего левого угла (каждый байт состоит ровно из 2 шестнадцатеричных цифр):

Байт: 0 1 2 3
Значение:  0x12  0x34  0x56  0x78

Самый старший байт нашего номера хранится по младшему адресу памяти (а младший байт сохраняется по старшему), что является старшим порядковым номером. Для порядка байтов наши числовые байты расположены в обратном порядке.

В заключение, люди думают, что они "порядочные".

Еще одна тема, которую я хочу охватить: типы (точнее, int). Python, основанный на C, наследует свои собственные типы, поэтому int будет иметь 4 байта (на некоторых платформах / архитектурах он может иметь 8). Таким образом, int (опять же, говоря о unsigned) имеет значение [0..4294967295]. Но даже для меньшего значения, например 5 (для которого требуется только 1 байт), оно все равно будет занимать 4 байта: (наиболее значимые) неиспользуемые байты будут дополнены 0 с. Таким образом, наше число в виде 4- байтового целого без знака будет (шестнадцатеричное): 0x00000005.

Теперь вернемся к нашей проблеме ( -ям ): как указано выше, 5 - это 0x05 (или 0x00000005 - 4- байтовое беззнаковое целое число) или в символах: \x00\x00\x00\x05, Но это в обратном порядке, чем то, что struct.pack дисплеи; Я думаю, что вы уже догадались, почему: это в представлении с прямым порядком байтов. Это дается 1- м (fmt) аргумент "<" часть, чтобы быть более точным) дано [Python 2]: struct. pack (возможные значения перечислены на той же странице: [Python 2]: порядок байтов, размер и выравнивание). Для 55555 все точно так же. Его шестнадцатеричное представление: 0xd903 или 0x0000d903.

Если это еще не имеет смысла, возьмите эту слегка измененную версию своего кода и поиграйте с ней, введя различные значения для 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:\Work\Dev\Stackru\q037990060>"C:\Install\x64\HPE\OPSWpython\2.7.10__00\python.exe" "code.py"
0x5 - \x05\x00\x00\x00
0xd903 - \x03\xd9\x00\x00
0x12345678 - xV4\x12
Другие вопросы по тегам