Как преобразовать uint32_t в массив без знака? - PullRequest
3 голосов
/ 08 мая 2019

Я пытаюсь реплицировать uint32_t значения преобразования в unsigned char массивы в Python (я уже сделал это в C)

Это моя существующая функция C:

unsigned char *uint32_to_char_array(const uint32_t n)
{
    unsigned char *a;

    a = wrap_calloc(4, sizeof(unsigned char));

    a[0] = (n >> 24) & 0xff;  /* high-order (leftmost) byte: bits 24-31 */
    a[1] = (n >> 16) & 0xff;  /* next byte, counting from left: bits 16-23 */
    a[2] = (n >>  8) & 0xff;  /* next byte, bits 8-15 */
    a[3] = n         & 0xff;  /* low-order byte: bits 0-7 */

    return a;
}

Если бы я сделал следующее в GDB:

(gdb) p uint32_to_char_array(0x00240918)[0]@4  = "\000$\t\030"

И эту строку я пытаюсь сгенерировать в python.

т.е. для uint32_t входного значения 0x240918 я хочу получить выходную строку "\000$\t\030"

Я искал SO, но пока безрезультатно, особенно это -> Как преобразовать целочисленное значение в массив из четырех байтов в python , но ни один из ответов не дает комбинацию ввода / вывода указано выше

Я использую 2.7, но при необходимости могу использовать> 3.0.

Обновление:

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x240918.to_bytes(4, "big")
b'\x00$\t\x18'

Хммм, немного по-другому - я уверен, что ответ смотрит мне прямо в лицо, но я не вижу, что это?

Итак, я вижу:

>>> b"\000$\t\030"
b'\x00$\t\x18'

Но как можно достичь обратного? т.е. * * одна тысяча тридцать две

>>> b'\x00$\t\x18'
b"\000$\t\030"

Может быть, вопрос в том, как я могу печатать байтовый литерал в восьмеричном, а не шестнадцатеричном формате?

1 Ответ

3 голосов
/ 08 мая 2019

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

30 восьмеричных, то есть "\030" этотакой же как 18 шестнадцатеричный то есть "\x18".Оба они представляют один байт в вашей последовательности байтов с десятичным значением 24.

Вы можете сравнить точные значения в REPL:

bytes((0x00240918 >> i & 0xff) for i in (24,16,8,0)) == b"\000$\t\030"
True

Проверьте документацию Pythonдля строковых и байтовых литералов :

  • \ooo Символ с восьмеричным значением ooo
  • \xhh Символ с шестнадцатеричным значением hh

Этиможет использоваться как в байтовых литералах, так и в строках (имейте в виду, что строки являются байтовыми последовательностями в Python 2).

Я не думаю, что bytes поддерживает восьмеричное представление по умолчанию (кодек ascii всегда используетhex), но вы можете написать свой собственный код:

import re
my_b = b'\x00$\t\x18'
print(re.sub(r'\\x([0-9a-f]{2})', lambda a: "\\%03o" % int(a.groups()[0], 16),
  str(my_b)))
# Console result: b'\000$\t\030'

Имейте в виду, что строка содержит дословные кавычки и префикс b', и она может принимать экранированные косые черты в виде шестнадцатеричной последовательности.Если вы действительно хотите получить хороший восьмеричный код __repr__, лучшим способом было бы создать цикл и проверить наличие непечатаемых символов, преобразовать их в восьмеричный трехзначный код и объединить все в строку.

...