大端和小端是计算机写内存的习惯。就如人类写文章时的顺序一般,现代人从左往右,古人却是竖书成行(自上而下写满一行后,再自右向左换行。);有些计算机规定从左往右写内存,有些规定从右往左写内存。
大端就是大地址在前,小端就是小地址在前。
前言:大端小端的历史发展
Little-Endian和Big-Endian这两个词最早来自格列夫游记用来讽刺政党之间的观点,一个坚持从小的那一端打破鸡蛋,另一个则坚持从大的那一端打破鸡蛋,我们都知道对于做饭而言,这两个没什么区别。
计算机Intel8088使用小端方式(相较于大端而言)是因为其能够完成在第一个内存周期执行操作,后来计算机数据总线宽度与寄存器宽度一致了,也就没有这个优势了。从操作者而言,小端模式利于计算,而大端模式则更易理解。对于具体的某一位bitPos,其含权大小bitValue是如何被计算的?[1]
- 小端 b i t V a l u e = 2 b i t P o s + 8 × b y t e P o s bitValue=2^{bitPos+8\times{bytePos}} bitValue=2bitPos+8×bytePos
对于大端模式你还得知道总的字节数量wordSize
- 大端 b i t V a l u e = 2 b i t P o s + 8 × w o r d S i z e − b y t e P o s − 1 bitValue=2^{bitPos+8\times{wordSize-bytePos-1}} bitValue=2bitPos+8×wordSize−bytePos−1
大端模式,第一个字节第一个数字就是符号位,小端需要找到最后一个字节的第一个数字。简单来说,权重计算小端优于大端,因为他不需要提前知道总的字节大小。
不同的计算机架构可能采用不同的字节序,这取决于CPU的设计和实现。一般来说,大端序的架构有:
- IBM System/370及其后续机型
- Motorola 68000系列
- PowerPC
- Java虚拟机
小端序的架构有:
- Intel x86及其兼容处理器
- ARM(默认小端序,但可以切换为大端序)
- Intel 8051
- Zilog Z80
还有一些架构可以支持双端序,也就是可以在运行时选择使用大端序或小端序,例如:
- MIPS
- ARM(可选大端序)
- DEC Alpha
- IA-64
一、数是按字节存储的
我们知道计算机是以字节为单位存储数据的,一个十进制数需要多少存储单元取决于其数的大小。
char arr[] = { 0x12,0x34 };
std::cout << "Big Endian will be:";
std::cout << ((0x34 << 8) + 0x12) << std::endl;
std::cout << "Little Endian will be:";
std::cout << ((0x12 << 8) + 0x34)<<std::endl;
char arr2[] = { 0x34,0x12 };
std::cout<<*(uint16_t *)arr2;
地址高低是什么意思?
假设我们眼前有一张充满格子的稿纸,规定从左往右,先写下的称为低地址,后写下的是高地址,这个规定和大小端没有关系。
对于一个词“你好”,正常情况,“你”写在左边,“好”写在右边,换句话说,“你”在低位,“好”在高位;当然如果你要特立独行一下,你也可以反过来,,“好”写在左边,“你”写在右边,换句话说,“你”在低位,“好”在高位;
左边的格子 | 右边的格子 |
---|---|
你 | 好 |
好 | 你 |
因为这是一个有意义的词,我们在阅读到这个词时,可以明确知道表达的是问候词“你好”,至于为什么不影响阅读,可以参考这里的讨论。
假设我们将一个欠款金额写在纸上,按照默认习惯2在左侧,1在右侧。
左边的格子 | 右边的格子 |
---|---|
2 | 1 |
这时候,写的顺序就尤为重要,因为不规定书写顺序,可能回导致不同的欠款金额:
- 从左往右正常写:21块
- 从右往左特殊写:12块
好家伙,差了9块钱。这也就说明,书写顺序对于解读来说是必要的,不同书写顺序可能导致记录的内容有不同的解读。
在计算机领域,正常写,我们称为大多数人写的方式为大端;特殊写,小部分人书写的方式为小端。
那么在实际编程中,这个规则是如何体现的呢?
我们知道计算机是以字节为单位存储数据,对于一个int型数据0x12345678(32位),必须将这个数分为四个字节写入以字节为计算机内存,顺序取决于计算机端种类。观察下面程序:
int a = 0x12345678;
char* ptr = (char *)&a;//因为char *恰好是一个字节,指针+1等于移动至下一个字节
std::cout << std::hex << (int)*ptr << std::endl;;
std::cout << std::hex << (int)*(ptr + 1) << std::endl;
std::cout << std::hex << (int)*(ptr + 2) << std::endl;
std::cout << std::hex << (int)*(ptr + 3) << std::endl;
如果是一个小端系统,那么那就应该是12 34 56 78;如果是一个大端系统,那么则为0x78 56 34 12,因为程序运行在x86,所以结果如下:
没错他是一个大端系统。
LSB MSB
LSB(Least Significant Bit) 权重最低的位,MSB(Most Significant Bit)权重最大的位。MSB是其实就是符号位,根据MSB所在是左端还是右端,可以很容易分出大小端:
MSB存在低地址中,没错他是一个内存存储方式是大端。
[1] https://stackoverflow.com/questions/4752715/why-are-both-little-and-big-endian-in-use
[2] 修改了事实错误,