Python进阶篇-struct字节对齐问题

Python进阶篇-struct字节对齐问题

Python调用C的时候,会传递一些复杂的数据结构,例如结构体,这时候就会遇到各种各样字节对齐的问题。下边所有的例子都是在windows 64bit下的结果。

格式字符串

说到这里我们就要来说一下python中的格式字符串,格式字符串顾名思义。就是一个字符串中的每一个字符代表一个数据类型。格式字符串由两部分构成,第一部分是字节序和对齐方式, 第二步是是具体的数据类型。python中格式字符和对应的数据类型关系如下表。

python struct字节sort python struct字节对齐_数据类型

例如“icc”,就代表要解析的结构体的三个成员数据类型是interger, char, char。

字节序和对齐

字节序和对齐,一共有下表5种方式

python struct字节sort python struct字节对齐_三步解决C语言中struct字节对齐问题_02

默认情况下,字节序和对齐字符是“@”,byte order中native 的意思就是和当前系统大的字节序一致,size如果是native则这个时候数据类型的大小和sizeof是一致的,如果是starndard,则这个时候数据类型的长度是固定的,和格式字符和数据类型中的长度是一致的。alignment是native的话,和当前系统的对齐方式一致。

需要注意的是,alignment是native的时候,字节对齐是和系统一致,但是在python中padding只会在连续的结构体成员之间添加,不会在结构体的开头和结尾添加

size = struct.calcsize(’@icc’) 结果是6。

size = struct.calcsize(’@cic’) 结果是9。

原因是系统字节对齐是4,第一个c和i之间添加了3个字节padding,但是最后一个c,后边没有添加padding,所以结果是9而不是12.

如何解决这个问题?当然有办法,在格式字符串的最后添加一个“0X”,“X”是一个数据类型,如“l”,代表的就是long,这时候就是指定数据类型,这时候就和C语言中的字节对齐完全一致。

size = size = struct.calcsize(’@cic0i’) 结果是12。

举个例子

在C代码中定义结构体:

Struct Person{
int fortune;
char height;
char weight;
};

假设从C代码中获取到的结构体数据是buf, 在python中使用struct模块按照上述的格式解析结构体中的数据。

python中使用struct.unpack(’@icc’, buf);解析结构体数据,这个时候就会报错。原因就是字节对齐导致两方的长度不一样。

size = struct.calcsize(’@icc’) 的结果是6,而sizeof(Person)的长度是8。这样就会导致解析错误。这是后需要指定格式对齐。

struct.unpack("@icc0i",buf)。这样就能正确解析C语言中的结构体。

希望能对大家有所帮助,祝大家在技术的道路上越走越远。

Python进阶篇-struct字节对齐问题相关教程