【发布时间】:2018-05-11 11:34:00
【问题描述】:
考虑以下程序:
#include <stddef.h>
#include <stdio.h>
typedef struct
{
unsigned bit:1;
unsigned char str[8];
} test;
#pragma pack(1)
typedef struct
{
unsigned bit:1;
unsigned char str[8];
} test_pack;
int main(int argc, char **argv) {
printf("%3lu str offset\n", offsetof(test, str));
printf("%3lu total\n", sizeof(test));
printf("%3lu str_pack offset\n", offsetof(test_pack, str));
printf("%3lu total\n", sizeof(test_pack));
return 0;
}
哪个输出
1 str offset
12 total
1 str_pack offset
9 total
在我的带有 GCC 4.8.4 的 Ubuntu 14.04.3 系统上。
(我认为)等效的 Python 程序,
#!/usr/bin/python3
from ctypes import *
class Test(Structure):
_fields_ = [
('bit', c_uint, 1),
('str', c_ubyte * 8),
]
class TestPacked(Structure):
_pack_ = 1
_fields_ = [
('bit_p', c_uint, 1),
('str_p', c_ubyte * 8),
]
if __name__ == "__main__":
print("%3lu str offset" % Test.str.offset)
print("%3lu total" % sizeof(Test))
print("%3lu str_p offset" % TestPacked.str_p.offset)
print("%3lu total_p" % sizeof(TestPacked))
输出
4 str offset
12 total
4 str_p offset
12 total_p
在同一系统上,运行 Python 3.4.0。
据我所知,位域应该占 1 位。 C 和 Python 都将其填充为 32 位,为结构添加 3 个字节的空白空间,以便更好地对齐。
但是,Python 将填充放在字符串之前,而 C 将其放在之后。
此外,对于 #pragma pack(1),C 会删除填充,但 Python 不会。
- 我可以让 python 在字符串之后而不是之前添加 3 个字节的填充吗?
- 如果做不到这一点,python 是否可以正确打包结构以便它们对齐?
不需要通过网络协议或任何东西跨不同系统工作...只是试图让位在一个系统上排队,即使我必须以某种方式重新配置它。谢谢!
【问题讨论】:
-
我解决了一个问题并创建了另一个问题...我将
c_uint(4 个字节)作为python 中位字段的类型,如果我将其更改为c_uint8(1 个字节)它行为与具有pragma pack(1)的 C 版本相同。这回答了我的第二个问题,但我仍然想知道如何保留填充,但按照 GCC 的方式将其移动到字符串之后。在类中添加_pack_ = 4似乎没有任何效果。 -
在这种情况下不要使用位域。让您的所有字段都属于某种可寻址类型。使用按位运算(例如按位和
&、移位<<或|等...)
标签: python padding ctypes memory-alignment