I'm trying to replicate conversion uint32_t
values to unsigned char
arrays in python (I've already done it in C)
This is my existing C function:
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;
}
If I were to do the following in gdb:
(gdb) p uint32_to_char_array(0x00240918)[0]@4 = "\000$\t\030"
And it's that string I'm trying to generate in python.
i.e. for a uint32_t
input value of 0x240918
I want an output string of "\000$\t\030"
I've scoured SO but to no avail thus far, particularly this -> How to convert integer value to array of four bytes in python but none of the answers seem to yield the input/output combination stated above
I'm using 2.7, but could use > 3.0 if required.
Update:
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'
Hmmm a bit different — I'm sure the answer is staring me in the face here but I can't see what it is?
So I can see:
>>> b"\000$\t\030"
b'\x00$\t\x18'
But how might one achieve the reverse? i.e.
>>> b'\x00$\t\x18'
b"\000$\t\030"
Maybe the question is how I can print a bytes-literal in octal rather than hexadecimal?
hmmm a bit different - i'm sure the answer is staring me in the face here but can't see what it is?
30 octal i.e. "\030"
is the same as 18 hexadecimal i.e. "\x18"
. Both of them represent a single byte in your byte sequence with a decimal value of 24.
You can compare the exact values in the REPL:
bytes((0x00240918 >> i & 0xff) for i in (24,16,8,0)) == b"\000$\t\030"
True
Check the Python documentation on string and byte literals:
\ooo
Character with octal value ooo\xhh
Character with hex value hhThese can be used in byte literals as well as strings (keep in mind that strings are byte sequences in Python 2).
I don't think bytes
support an octal representation by default (the ascii codec always uses hex), but you can code your own:
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'
Keep in mind that the string contains verbatim quotes and the b'
prefix, and it may accept escaped slashes as a hex sequence. If you really want a good octal __repr__
the best way would be to create a loop and check for non-printable characters, convert them to 3 digit octal and join everything into a string.