В python при использовании пакета он усекает мои биты MSB при упаковке длинной переменной,

    int1 = 11111111
    int2 = 22222222
    long1 = 6666666666666666   
    int3 = 33333333
    int4 = 44444444
    int5 = 55555555
    pack_list = (int1,int2,long1,int3,int4,int5)     
    pack_format = struct.Struct('> I I L I I I')              
    pack_data = pack_format.pack(*pack_list)   

    print "Original_values:", pack_list    
    print "Format_string:", pack_format.format     
    print "Uses:", pack_format.size,'bytes'   
    print "Packed_value:", binascii.hexlify(pack_data) 

У меня есть 64 бита в длинной переменной, но когда я упаковываю с использованием обратного порядка байтов, он обрабатывает его как целое число, которое вы можете видеть в выводе, показывающем как 24 байта вместо 28 байтов, что является фактической длиной данных. Может ли кто-нибудь сказать мне, что происходит, и помочь мне получить все 64 бита в упакованных данных с прямым порядком байтов?

Исходные значения: (11111111, 22222222, 66666666, 33333333, 44444444, 55555555) Format_string: > I I L I I I
Использование: 24 байта
Packed_value: 11111111222222254455555


person Phanendra Nath    schedule 08.06.2018    source источник
comment
Какую версию Python вы используете? Это должно вызывать исключение в 2.7 и 3.x, а не усекать молча.   -  person abarnert    schedule 08.06.2018
comment
В любом случае, для 64-битного int вам нужен формат Q, а не L.   -  person abarnert    schedule 08.06.2018
comment
Отлично, это работает, вы спасли мой день. Большое спасибо   -  person Phanendra Nath    schedule 08.06.2018
comment
но в документации я видел это как L, что означает Q   -  person Phanendra Nath    schedule 08.06.2018
comment
@PhanendraNath: предположительно четверное слово (по старой номенклатуре для 16-битного x86, где 16 бит - это слово, 32 - двойное слово / двойное слово, и хотя тогда этого не существовало, 64 бита позже были описаны как четверное слово, следующее за тем же шаблон).   -  person ShadowRanger    schedule 08.06.2018


Ответы (1)


Спецификатор формата L означает C long, который обычно имеет 32 бита — тот же размер, что и C int. Таким образом, ваше 64-битное число слишком велико для него. (Я почти уверен, что Python 2.7 и 3.x должны выдавать вам ошибку OverflowError или ValueError или что-то в этом роде, а не усекать молча… но в любом случае это не сработает.)

Спецификатор формата Q означает C long long, который обычно является 64-битным, так что это то, что вам нужно.

Если вам интересно, почему в Python есть и I, и L, когда они означают одно и то же, ну, на самом деле это просто потому, что в C есть и int, и long, но для этого есть или, по крайней мере, была причина. В настоящее время int почти всегда 32-битный, но когда Python был первоначально написан, обычно это был 16-битный или 32-битный код, который был быстрее на вашей платформе. Итак, если вы пытаетесь сопоставить структуру из какого-либо Unix API, определенного для использования int, вы должны использовать I; структура, определенная для использования long, вам пришлось использовать L; смешайте их, и ваш код не будет переносимым между разными системами.

И если вам интересно, почему q — это сокращение от long long — это действительно сокращение от «quad», по крайней мере косвенно. Скорее всего, это происходит из множества различных систем Unix, использующих q в качестве префикса спецификатора формата printf для своих нестандартных 64-битных типов (таким образом, %qd означает 64-битное целое число, напечатанное как десятичное число). Если нет, то, вероятно, Windows использует QWORD для 64-битной структуры из двух 32-битных целых чисел. В обоих случаях «q» означало «четверное»: 16 бит — это слово, 32 бита — двойное слово, а 64 бита — четверное слово. (В случае с printf также может иметь значение то, что было очень много однобуквенных префиксов. Позже стандарты C и POSIX обошли это, просто разрешив многобуквенные префиксы, так что теперь это %lld, который это сокращение от long long.)

person abarnert    schedule 08.06.2018