python struct 问题

阅读 4k
1 个回答

老铁, 以下内容仅供参考:

一.为什么 struct.calcsize("5id") 是32

C语言中结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题

拿C语言的结构体来说明一下:

fmt"5id"相当于下面这样的一个结构体:

struct s
{
    int i1, i2, i3, i4, i5;
    double j;
};

先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。

因此
第一个成员i1的偏移量为0。
第二个成员i2的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4), 其值为4
第三个成员i3的偏移量是第二个成员的偏移量加上第二个成员的大小(4+4), 其值为8
第四个成员i4的偏移量是第三个成员的偏移量加上第三个成员的大小(8+4), 其值为12
第五个成员i5的偏移量是第四个成员的偏移量加上第四个成员的大小(12+4), 其值为16
第六个成员j的偏移量是第五个成员的偏移量加上第五个成员的大小(16+4),其值为20.

实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:

一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体大小必须是所有成员大小的整数倍。

  对照第一条,上面的例子中前五个成员的偏移量都满足要求,但第六个成员j的偏移量为20,并不是自身(double)大小的整数倍。编译器在处理时会在第二个成员后面补上4个空字节,使得第三个成员的偏移量变成24。

  对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为32,满足要求。

所以, struct.calcsize("5id") 是32

参考自这位大佬的文章:计算结构体的大小:https://blog.csdn.net/csw_100...

二.如何定义fmt

Note: By default, the result of packing a given C struct includes pad bytes in order to maintain proper alignment for the C types involved; similarly, alignment is taken into account when unpacking. This behavior is chosen so that the bytes of a packed struct correspond exactly to the layout in memory of the corresponding C struct. To handle platform-independent data formats or omit implicit pad bytes, use standard size and alignment instead of native size and alignment: see Byte Order, Size, and Alignment for details.

默认情况下,打包给定C语言结构体的结果包括填充字节,以便维护所涉及的C语言类型的正确对齐; 类似地,在拆包时考虑对齐。选择此行为是为了使被打包结构的字节与相应C结构的内存中的布局完全对应。要处理与平台无关的数据格式或省略隐式填充字节,请使用standard大小与对齐而不是 native大小与对齐:有关详细信息,请参阅字节顺序,大小和对齐

我查了一下time_t, 应该是是长整型
参考自:C语言中time_t数据类型详细介绍
先告诉你答案吧:

fmt = '@5id'

那如何选择the first character of the format string

clipboard.png
图片来源: https://docs.python.org/3.6/l...

我就说说我的理解吧:

  • @ 是最常用的, 如果你需要填充对其, 那一定选它
  • = 格式字符的排序可能会对大小产生影响, 但如果你不想让顺序产生影响, 用它无疑, 但是他不会帮你填充对齐
  • 多用于网络字节, 我也不大懂(希望大佬帮忙解释下, 欢迎直接编辑), 也不会帮你填充对齐
  • > 本机字节顺序是big-endian, 也不大懂, 也不会帮你填充对齐
  • < 本机字节顺序是little-endian, 也不大懂, 也不会帮你填充对齐
这是官方的说明
! is available for those poor souls who claim they can’t remember whether network byte order is big-endian or little-endian.
'!'适用于那些声称无法记住网络字节顺序是big-endian还是little-endian的网络字节序

这是官网说的<, >的用法:
本机字节顺序是big-endian或little-endian, 具体取决于主机系统。
例如:

  • Intel x86AMD64(x86-64)little-endian;
  • 摩托罗拉68000PowerPC G5都是big-endian的;
  • ARMIntel Itanium具有可切换的字节序(bi-endian)

使用sys.byteorder来检查你的系统的字节序。

There is no way to indicate non-native byte order (force byte-swapping);
use the appropriate choice of < or >.
无法确认非本机字节使用< or >

参考自:
struct官方文档:https://docs.python.org/3/lib...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题