目录
[2.1 什么是大小端?](#2.1 什么是大小端?)
[2.2 为什么会有大小端之分?](#2.2 为什么会有大小端之分?)
[2.3 练习1](#2.3 练习1)
[2.4 练习2](#2.4 练习2)
[2.5 练习3](#2.5 练习3)
[2.6 练习4](#2.6 练习4)
[2.7 练习5](#2.7 练习5)
[2.8 练习6](#2.8 练习6)
[3.1 浮点数的存储](#3.1 浮点数的存储)
[3.2 浮点数存的过程](#3.2 浮点数存的过程)
[3.3 浮点数取的过程](#3.3 浮点数取的过程)
[3.4 题目解析](#3.4 题目解析)
正文开始
1.整数在内存中的存储
我们先来回顾一下,整数的表示方法:
- 整数的二进制表示方法有3种:原码、反码、补码。
- 有符号整数的最高一位为符号位, 0表示正,1表示负,其余位为数值位。
- 无符号整数没有符号位,所有的位都用来表示数值。
我们再来回顾一下,原码、反码和补码的概念:
- 原码:真值的符号部分用0或1来表示,真值的数值部分用二进制来表示。
- 反码:原码的符号位不变, 其他位取反。
- 补码:反码 + 1。
- 原码→补码:符号位不变,取反+1。
- 补码→原码:符号位不变,取反+1。
- 正整数的原、反、补都相同。
- 负整数的原、反、补各不相同。
我们还需要知道的是:
- 在计算机系统中,数值一律用补码来表示和存储。
- 原因在于,使用补码,可以将符号位和数值域统一处理。
- 同时,加法和减法也可以统一处理(CPU只有加法器)。
- 此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
2.大小端字节序
请看代码:

我们发现:0x11223344是以字节为单位,倒着存储的,即44332211。这是为什么呢?
2.1 什么是大小端?
刚刚的变量a,是int类型,大小为4个字节。像这样,超过1个字节的数据,在内存中存储的时候,就有存储顺序的问题了。按照不同的存储顺序,分为大端字节序存储和小端字节序存储,概念如下:
- 大端模式:数据的低位放在高地址处,高位放在低地址处。
- 小端模式:数据的低位放在低地址处,高位放在高地址处。
简而言之:
- 大端模式:正着存,如0x11223344→11 22 33 44。
- 小端模式:倒着存,如0x11223344→44 33 22 11。
2.2 为什么会有大小端之分?
2.3 练习1
- 在计算机系统中,数据的存储是以字节为单位的。
- 每个地址单元都对应着1个字节,1个字节有8个比特位。
- char是1个字节,但short是2个字节,int是4个字节......
- 对于超过1个字节的数据,它就需要分为多个字节来存储了,也就出现了存储顺序问题。
- 对于32位和64位这些处理器,由于寄存器的宽度大于1个字节,必然存在着顺序问题。
- 我们常用的x86结构是小端模式,而KEIL C51则为大端模式。
- 很多的ARM、DSP都为小端模式。
- 有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)------百度笔试题
我们可以以1为例,来进行大小端的判断。
如果是大端模式,即00 00 00 01,我们取出第一个字节,应该得到00。
如果是小端模式,即01 00 00 00,我们取出第一个字节,应该得到01。

2.4 练习2
请看代码:

这道题与整数在内存中的存储有关。

我们来看一下结果:
我们再看另一种情况,如果是以%u的形式打印呢?
2.5 练习3

我们来看一下分析及结果:

我们再看一道类似的题目:


2.6 练习4

2.7 练习5

再看一道类似的题目:
2.8 练习6

对于ptr[-1],我们可以看看图解:
我们再来看一下*ptr2的图解:
运行结果如我们所见:
上述代码运行的环境为32位环境,如果是64位环境,a是8字节的地址,强制转换为4字节的int类型,就会破坏地址的完整性了。
3.浮点数在内存中的存储
请看代码:
如上,我们可以发现,浮点数的存储方式,和整型是有差异的。
3.1 浮点数的存储
在上面的代码中,n和*pFloat在内存中明明是同一个数,为什么以浮点数和整数的视角解读,结果会有这么大的差异呢?
要理解这个结果,一定要搞明白浮点数在计算机内部的表示方法。
根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:

- S也叫数符,0表示整数, 1表示负数,用来决定浮点数的符号。
- M也叫尾数,是一个二进制的定点小数,一般用原码表示。
- E也叫阶码,是一个二进制的定点整数,一般用移码来表示。
我们来看一个例子:

IEEE754规定:
- 对于32位的浮点数 (float),最高1位 存储的是符号位S,后面8位 存储的是指数E,剩下23位存储的是有效数字M。
- 对于64位的浮点数 (double),最高1位 存储的是符号位S,后面11位 存储的是指数E,剩下52位存储的是有效数字M。
3.2 浮点数存的过程
前面提到过,根据IEEE 754标准,M都是写成1.xxxxxx的形式。可以发现,任何一个浮点数,第一位都是1。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以不用存这个1,只存后面的xxxxxx部分即可。
比如,在存1.01的时候,只存01,等到读取的时候,再把第一位加上去。
这样做的目的是,节省1位有效数字。以32位浮点数为例,留给M的只有23位,将第一位舍去后,相当于可以存24位有效数字了。
至于指数E,它是一个无符号整数(unsigned int)。
这意味着,如果E为8位,它的取值范围就是0~255;如果E为11位,它的取值范围就是0~2047。但是,我们知道,有时候E是会出现负数的,比如:0.5为(-1)^0*1.0*2^(-1),这里的E就是-1。所以IEEE 754规定,存入内存时,E的真实值必须再加上一个偏置值。对于8位的E,偏置值为127;对于11位的E,偏置值为1023。也就是,根据IEEE 754,对于n位的E,偏置值为2^(n-1) - 1。
比如,2^10的E是10,所以保存为32位浮点数时,必须保存为10+127=137,即10001001。
3.3 浮点数取的过程
指数E从内存中取出来,还可以再分为3种情况:
1.E不全为0或不全为1(常规情况):
符号位S不用处理。
指数E减去偏置值127(或1023),得到真实值。
有效数字M的第一位加上原来舍去的1。
2.E全为0:
这时,IEEE 754规定:
指数E的真实值为1-127(或1-1023)。
有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。
这样做是为了表示±0,以及表示接近于0的很小的数字。
3.E全为1:
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位S)。
3.4 题目解析
对于开头提到的代码,我们就进行一个解析:
完结