参考:https://blog.csdn.net/hackbuteer1/article/details/7722667#commentBox
大小端根据字节序分区分
为什么有大小端之分???
因为在计算机系统中,存储是以字节为单位的,每个地址单元都对应着一个字节,一个字节=8bit。在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,如何安排多个字节的存储(字节序),这就有了大端存储模式和小端存储模式
字节序:大于一个字节类型的数据在内存中的存放顺序,在跨平台以及网络程序中需要注意
分类:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。(低位数在低地址端)
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。(低位数在高地址端,类似于字符串排序)
c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。
注意:通常我们说的主机序(Host Order)就是遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序 (Little-Endian)和网络序(Big-Endian)的转换。
例子:
如果小端存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001 0x4002 0x4003
存放内容 0x78 0x56 0x34 0x12
而在Big- endian模式CPU内存中的存放方式则为:
内存地址 0x4000 0x4001 0x4002 0x4003
存放内容 0x12 0x34 0x56 0x78
大小端优缺点
Big-Endian优点:首先提取最高位字节(在低地址上),可以快速确定数的正负。即符号位的判定固定为第一个字节,容易判断正负。
Little-Endian优点:提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。即强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式.
代码测试大小端
首先了解c语言中的联合体或者共用体union:https://blog.csdn.net/huqinwei987/article/details/23597091:
union中的变量完全是共用一个内存首地址。
剖析:由于联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little- endian还是Big-endian模式读写。
#include <iostream>
using namespace std;
bool isBigEndian();
bool isLittleEndian();
int main()
{
if (isBigEndian())
cout << "大端" << endl;
else
cout << "小端" << endl;
if (isLittleEndian())
cout << "小端" << endl;
else
cout << "大端" << endl;
system("pause");
return 0;
}
//方法1
bool isBigEndian()
{
short int a = 0x1122;//16进制,一个数值占4位;short in占2个字节,16位
//8个字节对应16进制的两个数值,
//通过将short(2字节)强制类型转换成char单字节,
//b指向a的起始字节(低字节)
char b = *(char*)&a;
if (b == 0x11)//高位低址
{
return true;
}
else
return false;
}
//方法2:利用union,原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间,更易理解
bool isLittleEndian()
{
union temp
{
short int a;
char b;
}temp;
temp.a = 0x1234;//2字节16位对应16进制的4个数值
if (temp.b == 0x12)//高位低址:大端
{
return false;
}
else
return true;
}