gpt4 book ai didi

c - ctypes.struct(打包)中的 sizeof 与 C 中的打包结构不匹配

转载 作者:太空狗 更新时间:2023-10-29 17:13:48 25 4
gpt4 key购买 nike

我有一个用 C 语言编写的打包结构,我想用 Python 对其进行解析。我注意到 C(使用 GCC 4.9.2)和 Python 3.4.2 中的 ctypes 库之间的运算符 sizeof 返回的位域结构大小存在差异。

以下 C 代码按预期打印 5:

#include <stdio.h>
#include <stdint.h>

typedef struct __attribute__((packed)) {
uint32_t ch0 : 20;
uint32_t ch1 : 20;
} pkt_t;

int main(){
printf("sizeof(pkt_t): %d\n", sizeof(pkt_t));
return 0;
}

虽然 Python 中的(相同)代码打印出 8

import ctypes

class Packet(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('ch0', ctypes.c_uint32, 20),
('ch1', ctypes.c_uint32, 20),
]

print(ctypes.sizeof(Packet()))

看起来 _pack_ = 1 等同于 C 中的 __attribute__((aligned(1))),而不是 __attribute__((packed, aligned (1))) 这将使结构尽可能紧密地打包。有没有办法为 ctypes 结构启用 packed 属性?

最佳答案

ctypes 文档 https://docs.python.org/3/library/ctypes.html#structure-union-alignment-and-byte-order明确指出

By default, Structure and Union fields are aligned in the same way theC compiler does it. It is possible to override this behavior byspecifying a pack class attribute in the subclass definition. Thismust be set to a positive integer and specifies the maximum alignmentfor the fields. This is what #pragma pack(n) also does in MSVC.

这意味着它们不引用 gcc 的作用,而是引用 MSVC #pragma pack。请参阅:https://learn.microsoft.com/en-us/cpp/preprocessor/pack?view=vs-2019

n

(Optional) Specifies the value, in bytes, to be used for packing. Ifthe compiler option /Zp isn't set for the module, the default valuefor n is 8. Valid values are 1, 2, 4, 8, and 16. The alignment of amember is on a boundary that's either a multiple of n, or a multipleof the size of the member, whichever is smaller.

因此,观察到的行为的原因之一在于 MSVC 与 gcc 的编译器细节。

gcc 文档 https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Type-Attributes.html#Type-Attributes (抱歉,gcc 页面上没有 gcc-4.9.2 的文档),另一方面,cleary 告诉我们:

This attribute(packed), attached to struct or union type definition, specifiesthat each member (other than zero-width bit-fields) of the structureor union is placed to minimize the memory required. When attached toan enum definition, it indicates that the smallest integral typeshould be used.

在这种情况下,它们并没有说明任何边界要求,而内存占用量已最小化。跨字节边界放置位域是否有意义可能是另一个讨论的主题。为什么 __attribute__((aligned(1))) 实际上按预期设置结构,这对我来说似乎很合乎逻辑且一致,因为它明确地强制执行结构成员的字节对齐,这似乎不是通过指定 __attribute__((packed)) 来区分大小写。在第一种情况下,gcc 编译器也会对位字段强制执行字节对齐。

总结:

  • MSVC#pragma pack(n) 指定要放置在内存偏移量为 n 的倍数处的结构成员的对齐方式
  • gcc 的 __attribute__ ((aligned (n))) 要求结构(成员)的对齐
  • gcc 的 __attribute__ ((__packed__)) 要求最小化内存占用,即使这意味着位域字节边界被跨越
  • gcc 的打包和对齐属性的组合也要求减少内存占用,但也有强制对齐的限制。所以不跨越位域字节边界

关于c - ctypes.struct(打包)中的 sizeof 与 C 中的打包结构不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40454606/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com