大端、小端数据存储
大端:较高的有效字节存放在较低的存储器地址,较低的有效字节存放在较高的存储器地址。
小端:较高的有效字节存放在较高的的存储器地址,较低的有效字节存放在较低的存储器地址。
如果将一个32位的整数0x12345678存放到一个整型变量(int)中,这个整型变量采用大端或者小端模式在内存中的存储由下表所示。为简单起见,本文使用OP0表示一个32位数据的最高字节MSB(Most Significant Byte),使用OP3表示一个32位数据最低字节LSB(Least Significant Byte)。
地址偏移 | 大端模式 | 小端模式 |
---|---|---|
0x00 | 12(OP0) | 78(OP3) |
0x01 | 34(OP1) | 56(OP2) |
0x02 | 56(OP2) | 34(OP1) |
0x03 | 78(OP3) | 12(OP0) |
如果将一个16位的整数0x1234存放到一个短整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示:
地址偏移 | 大端模式 | 小端模式 |
---|---|---|
0x00 | 12(OP0) | 34(OP1) |
0x01 | 34(OP1) | 12(OP0) |
由上表所知,采用大小模式对数据进行存放的主要区别在于在存放的字节顺序,大端方式将高位存放在低地址,小端方式将高位存放在高地址。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。到目前为止,采用大端或者小端进行数据存放,其孰优孰劣也没有定论。
Python使用struct处理二进制
struct语句 | 格式 |
---|---|
pack(fmt, v1, v2, …) | 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) |
unpack(fmt, string) | 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple |
calcsize(fmt) | 计算给定的格式(fmt)占用多少字节的内存 |
struct中支持的格式如下表:
Format | C Type | Python | 字节数 |
---|---|---|---|
x | pad byte | no value | 1 |
c | char | string of length 1 | 1 |
b | signed char | integer | 1 |
B | unsigned char | integer | 1 |
? | _Bool | bool | 1 |
h | short | integer | 2 |
H | unsigned short | integer | 2 |
i | int | integer | 4 |
I | unsigned int | integer or long | 4 |
l | long | integer | 4 |
L | unsigned long | long | 4 |
q | long long | long | 8 |
Q | unsigned long long | long | 8 |
f | float | float | 4 |
d | double | float | 8 |
s | char[] | string | 1 |
p | char[] | string | 1 |
P | void * | long |
- 注1.q和Q只在机器支持64位操作时有意思
- 注2.每个格式前可以有一个数字,表示个数
- 注3.s格式表示一定长度的字符串,4s表示长度为4的字符串,但是p表示的是pascal字符串
- 注4.P用来转换一个指针,其长度和机器字长相关
- 注5.最后一个可以用来表示指针类型的,占4个字节
为了同c中的结构体交换数据,还要考虑有的c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下:
Character | Byte order | Size and alignment |
---|---|---|
@ | native | native |
= | native standard | 按原字节数 |
< | little-endian | standard 按原字节数 |
> | big-endian | standard 按原字节数 |
! | network (= big-endian) | standard 按原字节数 |
struct.unpack_from(fmt, buffer, offset)
fmt: 内容解析格式,其中B表示的是一个字节, > 表示的是大端法则,content_numb表示的是多少个字节。