结构w /位字段:CPython和C填充不同
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了结构w /位字段:CPython和C填充不同,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3252字,纯文字阅读大概需要5分钟。
内容图文
![结构w /位字段:CPython和C填充不同](/upload/InfoBanner/zyjiaocheng/735/d1a3f9890eb3470ea8c9389e492f117b.jpg)
考虑以下程序:
#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
在我的Ubuntu 14.04.3系统上使用GCC 4.8.4.
(我认为)等效的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标准(参考C11的ref n1256草案)在6.7.2.1结构和联合说明符中说:
…
§4 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed
int, unsigned int, or some other implementation-defined type.
…
9 A bit-field is interpreted as a signed or unsigned integer type consisting of the specified
number of bits
好吧,你想要一个使用一个位的无符号类型,但下一段说(强调我的):
10 An implementation may allocate any addressable storage unit large enough to hold a bitfield.
这里一个字节就足够了,所以gcc将使用一个字节.但32位模式下的MSVC将使用4个字节,C程序的输出将为:
4 str offset
12 total
4 str_pack offset
12 total
正是CPython实现输出的内容
这意味着ctypes实施者选择在这里关注MSVC.模块文档中的两个句子提供了一个提示,除了大多数示例使用Windows的事实:
> 16.16.1.10中的警告.结构和工会¶
Warning: ctypes does not support passing unions or structures with bit-fields to functions by value. While this may work on 32-bit x86, it’s not guaranteed by the library to work in the general case.
和下一段陈述于16.16.1.11.结构/联合对齐和字节顺序
By default, Structure and Union fields are aligned in the same way the C compiler does it… This is what #pragma pack(n) also does in MSVC
问题是ctypes模块实现者选择了一个约定 – 它们不能直接依赖于编译器,因为位字段的大小必须是常量 – 与平台无关.您可能认为这是非MSVC实现的问题并填写错误报告,但我也认为ctypes模块主要用于Windows.
因此,能够在此处理C结构的唯一方法是明确强制位字段的基础类型,并将第一个字段声明为无符号字节,并最终指定显式填充:
class Test(Structure):
_fields_ = [
('bit', c_byte),
('str', c_ubyte * 8),
('', c_ubyte * 3), # explicit padding
]
class TestPacked(Structure):
_fields_ = [
('bit_p', c_ubyte),
('str_p', c_ubyte * 8),
]
但这只是一种解决方法,因为这里bit和bit_p是普通字节,而C代码要求只使用1位,其他7位是填充位.
内容总结
以上是互联网集市为您收集整理的结构w /位字段:CPython和C填充不同全部内容,希望文章能够帮你解决结构w /位字段:CPython和C填充不同所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。