pack a three byte int

p.lavarre at p.lavarre at
Fri Nov 10 04:08:42 CET 2006

> > ... Python can say six-nybble hex:
> >
> > >>> import binascii
> > >>> cdb = binascii.unhexlify('%02X%06X%02X%02X' % (0x08, 0x12345, 0x80, 0))
> > >>> binascii.hexlify(cdb)
> >'080123458000'
> The only problem I can see is that this code is endianness-dependent;
> the suggested versions using pack(">...") not. But this may not be of
> concern to you.

Thanks for cautioning us.  I suspect we agree:

i) pack('>...') can't say three byte int.
ii) binascii.hexlify evals bytes in the order printed.
iii) %X prints the bytes of an int in big-endian order.
iv) struct.unpack '>' of struct.pack '<' flips the bytes of an int
v) struct.unpack '<' of struct.pack '>' flips the bytes of an int
vi) [::-1] flips a string of bytes.

In practice, all my lil-endian structs live by the C/Python-struct-pack
law requiring the byte size of a field to be a power of two, so I can
use Python-struct-pack to express them concisely.  Only my big-endian
structs are old enough to violate that recently (since ~1972)
popularised convention, so only those do I construct with

Often I wrap a big-endian struct in a lil-endian struct, but I'm ok
calling hexlify to make the big-endian struct and then catenating it
into the lil-endian struct, e.g., in the following cdb is big-endian
inside cbwBytes:

		cbwBytes = struct.pack('<IIIBBB',
			cbw.dSignature, cbw.dTag, cbw.dDataTransferLength,
			cbw.bmFlags, cbw.bLun, cbw.bCbLength,
			) + cdb[0:cdbLength] + ('\0' * (0x10 - cdbLength))

More information about the Python-list mailing list