Python 3.1.3 ctypes.struct 未正确排序位并意外修改数据
我定义了以下结构,
import ctypes
from ctypes import *
class r( BigEndianStructure ):
_fields_ = [( "d0", c_uint32, 28 ),
( "d1", c_uint32, 18 ),
( "d2", c_uint32, 18 ),
( "d3", c_uint16, 16 ),
( "d4", c_uint16, 16 ), ]
然后使用以下代码进行测试
a = r(0xAAAAAAAA,0xBBBBBBBB,0xCCCCCCCC,0xDDDD,0xEEEE)
for byte in string_at( addressof( a ), sizeof( a ) ):
print(hex(byte),end="")
,结果是
0xaa 0xaa 0xaa 0xa0 0xee 0xee 0xc0 0x0 0x33 0x33 0x0 0x0 0xdd 0xdd 0xee 0xee
预期结果
0xaa 0xaa 0xaa 0xa0 0xbb 0xbb 0xc0 0x0 0xcc 0xcc 0xc0 0x0 0xdd 0xdd 0xee 0xee
不仅结构未压缩,而且结果数据与输入的数据不同。是我犯了什么错误还是Python喜欢用自己的想法修改数据?
I defined the following structure
import ctypes
from ctypes import *
class r( BigEndianStructure ):
_fields_ = [( "d0", c_uint32, 28 ),
( "d1", c_uint32, 18 ),
( "d2", c_uint32, 18 ),
( "d3", c_uint16, 16 ),
( "d4", c_uint16, 16 ), ]
then tested with the following code
a = r(0xAAAAAAAA,0xBBBBBBBB,0xCCCCCCCC,0xDDDD,0xEEEE)
for byte in string_at( addressof( a ), sizeof( a ) ):
print(hex(byte),end="")
result is
0xaa 0xaa 0xaa 0xa0 0xee 0xee 0xc0 0x0 0x33 0x33 0x0 0x0 0xdd 0xdd 0xee 0xee
the expected result was
0xaa 0xaa 0xaa 0xa0 0xbb 0xbb 0xc0 0x0 0xcc 0xcc 0xc0 0x0 0xdd 0xdd 0xee 0xee
not only the structure was not compacted, the result data is different than what was entered. did I made any mistake or Python likes to modify data with its own mind?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来问题来自于将 18 位宽度值存储在 32 位中,然后将它们解释为完整的 32 位值。
让我们看看
0xBBBBBBBB
发生了什么:如果您的结构看起来像
| d0 | 4 个填充位 | d1 | 14 个填充位 | d2 | 14 个填充位 ... |
然后将d1
的地址解释为 32 位值将是:基本上在像这样读取内存时,而不是获取该值的 18 位掩码如您所料,您将得到 14 位移位。
It looks like the issue comes from storing the 18 bit width values in 32 bits, and then interpreting them as full 32 bit values.
Lets look at what is happening with
0xBBBBBBBB
:If your structures looks like
| d0 | 4 pad bits | d1 | 14 pad bits | d2 | 14 pad bits ... |
then interpreting the address ofd1
as a 32 bit value will be:Basically when reading the memory like this, instead of getting the 18 bit mask of the value you expect, you are getting a 14 bit shift.
字段左对齐(向右填充)
字段 d0 -
字段 d1 -
字段 d2 -
字段 d1 和字段d2 不能同时容纳在 32 位字段中 - 因此 d2 在下一个 32 位槽中对齐。
字段 d1 的说明性分步示例:
The fields are left aligned (padded to the right)
Field d0 -
Field d1 -
Field d2 -
Fields d1 & d2 will not both fit within a 32 bit field - so d2 is aligned in the next 32 bit slot.
Illustrative step-by-step example for field d1:
使用适合容器类型的位字段以避免对齐填充。在下面的示例中,4+8+16 适合 c_uint32,但 4+8+16+5 不适合,因此 d3 在下一个 c_uint32 中对齐:
输出
二进制输出使数字更易于可视化。请注意,第一个 c_uint32 的剩余 4 位无法容纳 5 位字段,因此添加了 4 位填充以开始下一个 c_uint32 中的 5 位字段。
Use bit fields that fit in a container type to avoid alignment padding. In the example below, 4+8+16 fit in c_uint32, but 4+8+16+5 does not, so d3 aligns in the next c_uint32:
Output
Binary output makes the numbers easier to visualize. Note that the 5-bit field couldn't fit in the remaining 4 bits of the first c_uint32, so 4 bits of padding were added to start the 5-bit field in the next c_uint32.