大端小端基本概念
计算机存储以字节为单位,除开少数可以支持位寻址的单片机(8051,8052等)以外,CPU最小的访存单元为8个比特位即一个字节,那么对于超过一个字节的数据类型在内存中的存储有以下两种模式。
- 大端模式(Big_endian): 字节数据的高字节存储在低地址中,而字节数据的低字节存储在高地址中。
- 小端模式(little_endian):字节数据的高字节存储在高地址中,而字节数据的低地址存储在低地址中。
以int数据类型举例。假设int在内存中的大小为两个字节,即占16位,有如下代码:
int a = 0x1234;
char* p = &a;
如果为大端模式,那么p[0] = 0x12, p[1] = 0x34;
如果为小端模式,那么p[0] = 0x34, p[1] = 0x12;
判断当前系统是大端还是小端
//判断当前系统是大端模式还是小端模式
int check_endian(void) {
int a = 0x1234;
char* p = (char*)&a;
if (*p == 0x34) {
return 0;// little_endian 低字节存放在低地址
} else {
return 1;// Big_endian 高字节存放在高地址
}
}`
怎么记大端小端?
总结一个比较好记录大小端概念的方法,只需要记录一个词即可:小低低,即可谐音为小弟弟。
可以理解为,小端模式,低字节数据存放在低地址,如此,大端模式相反即可。
网络字节序与主机字节序
网络字节序是一种用于网络传输的字节序,其采用大端模式。
主机字节序指的是当前主机所使用的字节序,具体跟CPU的设计有关,有可能是大端模式,也有可能是小端模式。
当主机需要通过网络进行通信时,需要将主机字节序转换为网络字节序,以确保数据的正确性。
其他场景下的一些应用
1. 将结构体数据或枚举类型强转为字节数组
有如下代码:
typedef struct AAA {
int a;
char b;
} aaa;
aaa st_a;
char* p;
st_a.a = 0x1234;
st_a.b = 255;
p = &st;
如果将以上代码中的p通过某一类型接口与其他设备进行交互,而没有约束好大小端类型,则当两个设备之间的大小端顺序不一致时,取到的将会是截然不同的数据。
2. 位域的使用
当系统为了精简内存的使用或者其他原因时,需要使用到位域,则必须要考虑大小端的形式。
struct message {
signed int little:4;
unsigned int x_set:1;
unsigned int y_set:1;
}message_trunk;
如上结构体,在使用时一定要注意不同系统采用的究竟是大端莫斯还是小端模式,以避免没必要可能产生的问题,