Используйте битовые поля, которые соответствуют типу контейнера, чтобы избежать выравнивания выравнивания. В приведенном ниже примере 4 + 8 + 16 соответствует c_uint32, а 4 + 8 + 16 + 5 - нет, поэтому d3 выравнивается в следующем c_uint32:
from ctypes import *
class r( BigEndianStructure ):
_fields_ = [('d0',c_uint32, 4),
('d1',c_uint32, 8),
('d2',c_uint32,16),
('d3',c_uint32, 5)]
def fld(n):
return '[' + '-'*(n-2) + ']'
def pad(n):
return '.'*n
print(fld(4),fld(8),fld(16),pad(4),fld(5),pad(27),sep='')
for i in range(1,17):
v = 2**i-1
a = r(v,v,v,v)
for byte in string_at( addressof( a ), sizeof( a ) ):
print('{0:08b}'.format(byte),end='',sep='')
print()
выход
Двоичный вывод облегчает визуализацию чисел. Обратите внимание, что 5-битное поле не может поместиться в оставшиеся 4 бита первого c_uint32, поэтому были добавлены 4 бита заполнения для запуска 5-битного поля в следующем c_uint32.
[--][------][--------------]....[---]...........................
0001000000010000000000000001000000001000000000000000000000000000
0011000000110000000000000011000000011000000000000000000000000000
0111000001110000000000000111000000111000000000000000000000000000
1111000011110000000000001111000001111000000000000000000000000000
1111000111110000000000011111000011111000000000000000000000000000
1111001111110000000000111111000011111000000000000000000000000000
1111011111110000000001111111000011111000000000000000000000000000
1111111111110000000011111111000011111000000000000000000000000000
1111111111110000000111111111000011111000000000000000000000000000
1111111111110000001111111111000011111000000000000000000000000000
1111111111110000011111111111000011111000000000000000000000000000
1111111111110000111111111111000011111000000000000000000000000000
1111111111110001111111111111000011111000000000000000000000000000
1111111111110011111111111111000011111000000000000000000000000000
1111111111110111111111111111000011111000000000000000000000000000
1111111111111111111111111111000011111000000000000000000000000000