2017-03-22 40 views
0

不同的結果,我使用的具有特定位長度的ctypes和大和小字節序的結構類型(S)和字段時看到不同的結果。我希望字節中的位排序對於兩個endianes都是一樣的,但結果提供了不同的答案。結果來自intel盒子上的一個6.8,64位的發行版。ctypes的bigendianstructure littlendianstructure返回單字節

>>> import ctypes 
>>> 
>>> class header_struct(ctypes.Structure): 
...  _fields_ = [ ('f1',ctypes.c_ubyte,4), 
...     ('f2',ctypes.c_ubyte,4) ] 
... 
>>> class header_struct_be(ctypes.BigEndianStructure): 
...  _fields_ = [ ('f1',ctypes.c_ubyte,4), 
...     ('f2',ctypes.c_ubyte,4) ] 
... 
>>> class header_struct_le(ctypes.LittleEndianStructure): 
...  _fields_ = [ ('f1',ctypes.c_ubyte,4), 
...     ('f2',ctypes.c_ubyte,4) ] 
... 
>>> a='\x0A' 
>>> x=header_struct.from_buffer_copy(a) 
>>> x_be=header_struct_be.from_buffer_copy(a) 
>>> x_le=header_struct_le.from_buffer_copy(a) 
>>> 
>>> print " sizeof(x) ", ctypes.sizeof(x) 
sizeof(x) 1 
>>> print " sizeof(x_be) ", ctypes.sizeof(x_be) 
sizeof(x_be) 1 
>>> print " sizeof(x_le) ", ctypes.sizeof(x_le) 
sizeof(x_le) 1 
>>> 
>>> x.f1 
10 
>>> x_be.f1 
0 
>>> x_le.f1 
10 
>>> 
>>> 
>>> x.f2 
0 
>>> x_be.f2 
10 
>>> x_le.f2 
0 
>>> 
+0

咩,這確實是不直觀的結果我不知道誰downvoted的問題。 – jsbueno

回答

0

一個字節內的位階是不是這兩個字節順序相同的 - 當然,在任何架構,您的號碼複製到一個字節,你得到相同的字節。而在這兩種架構中,最低有效位都是作爲位「0」尋址的。由於數據以字節爲單位移動,而這只是仿真,無論如何,這些位值實際上並未在內存中的x86架構中鏡像。這對於watty ctypes是有效的,並且很可能你會產生與你一起玩的C代碼。

但是,如果細分的領域一個字節,這些領域的相對位置是字節內的鏡像 -

可以使用ctypes.Union結構(這樣也排除填充檢查,在一個更簡單的方法-bytes副作用,當你看到的數字)的可能原因:

import ctypes 
class header_struct(ctypes.Structure): 
     _fields_ = [ ('f1',ctypes.c_ubyte,4), 
        ('f2',ctypes.c_ubyte,4) ] 

class big_endian(ctypes.BigEndianStructure): 
     _fields_ = [ ('b{}'.format(i), ctypes.c_ubyte, 1) for i in range(8) ] 
class little_endian(ctypes.LittleEndianStructure): 
     _fields_ = [ ('b{}'.format(i), ctypes.c_ubyte, 1) for i in range(8) ] 

class le_byte(ctypes.LittleEndianStructure): 
    _fields_ = [('value', ctypes.c_ubyte)] 

class be_byte(ctypes.BigEndianStructure): 
    _fields_ = [('value', ctypes.c_ubyte)] 

class Union(ctypes.Union): 
    _fields_ = [('le', le_byte), ('be', be_byte), ('lebits', little_endian), ('bebits', big_endian)] 

和交互控制檯上:

In [319]: u = Union() 

In [320]: u.le.value = 0x80 

In [321]: u.be.value # not mirrored 
Out[321]: 128 

In [322]: u.lebits.b7 
Out[322]: 1 

In [323]: u.lebits.b0 
Out[323]: 0 

In [324]: u.bebits.b7 
Out[324]: 0 

In [325]: u.bebits.b0 
Out[325]: 1 

眼看你可能從事一些實際的代碼,而不僅僅是一起演奏,我的建議是保持有處理子字節領域LittleEndianStructure所有結構,並創建一個聯盟與相同的字節大小的BigEndianStructure每當你必須從緩衝區複製字節來做你的I/O。

以另一種方式把,只是要確保它是明確的:所有的子字節位maniplation上宣佈爲LittleEndian結構進行。然後,要將多字節數據複製到此結構中,並將其與另一個只包含整數個字節的字段(可以聲明爲BigEndian)的結構合併,並執行所有引用此數據的數據複製其他結構。

而且,做了很多測試,對整個事情:-)。