一点一点前进...

0%

大端 vs. 小端

说到数据在内存中的布局问题就不得不提到另一个概念:大端和小端。
存储地址内的排列则有两个通用规则。一个多位的整数将按照其存储地址的最低或最高字节排列。如果最低有效字节在最高有效字节的前面,则称小端序;反之则称大端序。

先来看个实际例子。

1
2
3
int i = 1 << 15;
short s = * (short*) &i;
std::cout << s << std::endl;

如果是大端机器,i的布局是0x00 0x00 0x80 0x00,s所对应的就是0x00 0x00,即0。
如果是小端机器,i的布局是0x00 0x80 0x00 0x00,s所对应的就是0x00 0x80,即-32768。

再来看个例子加深下理解。

1
2
3
float f = 7.0;
short s = * (short*) &f;
std::cout << s << std::endl;

7.0 = 1.75 * 2 ^ (129 - 127)
在大端机器中,对应的内存分布是一个0,接下来八位是10000001,接下来是两个1,后面都是0。s对应的是一个挺大的数字。在小端机器中,按照字节翻转,后面的0都跑前面来了,那么s就是0。

我们可以用一个简单的程序来检测到底是大端还是小端(当然,上面的两个例子也能检测)

1
2
3
4
5
6
7
8
9
10
int i = 1;
char ch = * (char*) &i;
if(ch == 1)
{
std::cout << "little endian" << std::endl;
}
else
{
std::cout << "big endian" << std::endl;
}

现在的机器几乎都是小端了,这是为什么呢?小端机器有什么好处呢?
StackOverflow和StackExchange上的答案类似:
使用同样的地址,可以使用不同的长度去读取一个变量。比如32bit的值,我们想读8bit或者16bit,直接读就好了,结果就是我们想要的,如果是大端,计算机还要计算偏移量再读取。
不过,在Quora上最高票答案是一个CPU Designer的回答,说是几乎没有什么区别。就和大端小端的来源一样,你会关心敲鸡蛋先敲开哪一端吗?
对于大多数程序员而言,现成的工具/库都考虑了这个问题,不用自己操心。不过,还是知道这个知识点比较好,说不准那天程序没有跑对就是因为这个呢?是吧。还有一点,万一面试的时候用呢。