大端和小端是指数据在内存中的存储模式,它由 CPU 决定:
1)  大端模式( Big-endian ) 是指将数据的低位(比如 1234 中的 34 就是低位)放在内存的高地址上,而数据的高位(比如 1234 中的 12 就是高位)放在内存的低地址上。这种存储模式有点儿类似于把数据当作字符串顺序处理,地址由小到大增加,而数据从高位往低位存放。

2)  小端模式( Little-endian ) 是指将数据的低位放在内存的低地址上,而数据的高位放在内存的高地址上。这种存储模式将地址的高低和数据的大小结合起来,高地址存放数值较大的部分,低地址存放数值较小的部分,这和我们的思维习惯是一致,比较容易理解。

为什么有大小端模式之分


计算机中的数据是以字节(Byte)为单位存储的,每个字节都有不同的地址。现代 CPU 的位数(可以理解为一次能处理的数据的位数)都超过了 8 位(一个字节),PC机、服务器的 CPU 基本都是 64 位的,嵌入式系统或单片机系统仍然在使用 32 位和 16 位的 CPU。


对于一次能处理多个字节的CPU,必然存在着如何安排多个字节的问题,也就是大端和小端模式。以 int 类型的 0x12345678 为例,它占用 4 个字节,如果是小端模式(Little-endian),那么在内存中的分布情况为(假设从地址 0x 4000 开始存放):


内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x78

0x56

0x34

0x12


如果是大端模式(Big-endian),那么分布情况正好相反:


内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x12

0x34

0x56

0x78




我们的 PC 机上使用的是 X86 结构的 CPU,它是小端模式;51 单片机是大端模式;很多 ARM、DSP 也是小端模式(部分 ARM 处理器还可以由硬件来选择是大端模式还是小端模式)。



借助共用体,我们可以检测 CPU 是大端模式还是小端模式,请看代码:

1. #include <stdio.h>
2. int main(){
3. union{
4. int n;
5. char ch;
6. } data;
7. 
8. .n = 0x00000001;  //也可以直接写作 data.n = 1;
9. if(data.ch == 1){
10. printf("Little-endian\n");
11. }else{
12. printf("Big-endian\n");
13. }
14. return 0;
15. }

在PC机上的运行结果:

Little-endian



共用体的各个成员是共用一段内存的。1 是数据的低位,如果 1 被存储在 data 的低字节,就是小端模式,这个时候 data.ch 的值也是 1。如果 1 被存储在 data 的高字节,就是大端模式,这个时候 data.ch 的值就是 0。

输出int时,先输出高位,再是低位。若是小端就是高地址->低地址,若是大端,低地址->高地址。


大端和小端是指数据在内存中的存储模式,它由 CPU 决定:

1) 

大端模式( Big-endian ) 是指将数据的低位(比如 1234 中的 34 就是低位)放在内存的高地址上,而数据的高位(比如 1234 中的 12 就是高位)放在内存的低地址上。这种存储模式有点儿类似于把数据当作字符串顺序处理,地址由小到大增加,而数据从高位往低位存放。


2) 

小端模式( Little-endian ) 是指将数据的低位放在内存的低地址上,而数据的高位放在内存的高地址上。这种存储模式将地址的高低和数据的大小结合起来,高地址存放数值较大的部分,低地址存放数值较小的部分,这和我们的思维习惯是一致,比较容易理解。

为什么有大小端模式之分


计算机中的数据是以字节(Byte)为单位存储的,每个字节都有不同的地址。现代 CPU 的位数(可以理解为一次能处理的数据的位数)都超过了 8 位(一个字节),PC机、服务器的 CPU 基本都是 64 位的,嵌入式系统或单片机系统仍然在使用 32 位和 16 位的 CPU。


对于一次能处理多个字节的CPU,必然存在着如何安排多个字节的问题,也就是大端和小端模式。以 int 类型的 0x12345678 为例,它占用 4 个字节,如果是小端模式(Little-endian),那么在内存中的分布情况为(假设从地址 0x 4000 开始存放):


内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x78

0x56

0x34

0x12


如果是大端模式(Big-endian),那么分布情况正好相反:


内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x12

0x34

0x56

0x78




我们的 PC 机上使用的是 X86 结构的 CPU,它是小端模式;51 单片机是大端模式;很多 ARM、DSP 也是小端模式(部分 ARM 处理器还可以由硬件来选择是大端模式还是小端模式)。



借助共用体,我们可以检测 CPU 是大端模式还是小端模式,请看代码:

1. #include <stdio.h>
2. int main(){
3. union{
4. int n;
5. char ch;
6. } data;
7. 
8. .n = 0x00000001;  //也可以直接写作 data.n = 1;
9. if(data.ch == 1){
10. printf("Little-endian\n");
11. }else{
12. printf("Big-endian\n");
13. }
14. return 0;
15. }


在PC机上的运行结果:

Little-endian



共用体的各个成员是共用一段内存的。1 是数据的低位,如果 1 被存储在 data 的低字节,就是小端模式,这个时候 data.ch 的值也是 1。如果 1 被存储在 data 的高字节,就是大端模式,这个时候 data.ch 的值就是 0。

输出int时,先输出高位,再是低位。若是小端就是高地址->低地址,若是大端,低地址->高地址。