struct.unpack()默认按本机字节序解析,若与C程序写入的字节序不匹配会导致数值错误;解决方法是在格式字符串开头显式指定字节序:''或'!'表示大端(网络序)。

struct.unpack() 解析二进制数据时字节序不匹配导致值异常
Python struct.unpack() 默认按本机字节序(sys.byteorder)解析,而 C 程序写入的二进制文件常显式指定字节序(如网络字节序 big-endian)。若不显式声明,int32_t 可能被读成完全错误的数值,比如 b'\x00\x00\x00\x01' 在小端机上解出 16777216 而非 1。
解决方法是始终在格式字符串开头加上字节序标识符:
' 表示 little-endian(对应 C 的 <code>uint32_t在 x86 写入)-
'>'表示 big-endian(对应htonl()写入) -
'!'表示 network byte order(等价于'>') - 省略或使用
则依赖本机,**不可移植**</li> </ul> <p>例如:C 端用 <code>write(fd, &val, sizeof(int32_t))
在 Linux x86 直接写入,Python 应用struct.unpack('<i data>;若 C 端用 <code>htons()写两个字节,则 Python 用'>H'。处理 C 结构体中的 padding 和对齐问题
C 编译器会按目标平台默认对齐规则(如 4 字节对齐)在结构体字段间插入 padding 字节,而
struct.unpack()不自动跳过这些字节——它只认格式字符串里写的字段。直接按字段类型拼格式(如'iif')很可能因忽略 padding 导致后续字段偏移错乱。立即学习“Python免费学习笔记(深入)”;
正确做法是:先用 C 的
offsetof()或sizeof()确认实际内存布局,再把 padding 显式写进格式串:- 用
'x'表示单字节 padding - 用
'2x'表示两字节 padding - 用
'c'+ord()验证某字节是否为预期 padding 值(如全零)
示例:C 中
struct { char a; int b; };在 gcc x86_64 实际占 8 字节(a后有 3 字节 padding),对应 Python 格式应为'cxxx i',而非'ci'。解析含固定长度字符数组(如 char name[32])的结构体
C 中
char name[32]是定长字节数组,不是以'\0'结尾的字符串。直接用'32s'解出的是带可能乱码的bytes,不能直接当 str 用;若用'32p'(Pascal string)则完全错误——'p'期望首字节为长度,与 C 数组语义不符。安全做法分两步:
- 用
'32s'解出原始bytes - 调用
.rstrip(b'\x00').decode('utf-8', errors='replace')清除末尾空字节并转字符串
注意:若 C 端可能写入非 UTF-8 字节(如路径含 GBK 编码),需按实际编码 decode;
errors='ignore'比'replace'更适合二进制日志场景。嵌套结构体或变长字段无法直接用 struct.unpack()
struct模块只支持固定长度、编译期已知布局的结构体。遇到 C 中的struct { int count; MyItem items[]; }(柔性数组)或含指针/联合体的结构,struct.unpack()无能为力——它不解析内存地址,也不处理运行时长度。可行路径只有两条:
- 先用
struct.unpack()解出头部(如count),再用循环对每个items[i]单独 unpack(需预先知道单个MyItem的格式和长度) - 改用
ctypes:定义对应Structure子类,用_fields_描述布局,再用from_buffer_copy()加载整块内存——它能处理数组、嵌套结构甚至 bitfield
别试图用
struct模拟指针跳转:C 的char*在 Python 里只是数字地址,没有上下文就无法还原所指内容。 - 用


















