目录
PS .
一.字节序
1.概念
" 字节序是CPU对内存中的数据以字节为单位进行存储的顺序,由于内存是有高低地址之分,数据的二进制形式也有高低位之分,按照高低位存储顺序的不同,把其分为大端和小端两类。 "
2.目的
若不同主机的数据存储形式不同,则不同主机之间无法进行网络通信,所以需要字节序来统一。
若不同主机之间的字节序不同,则在通信时会造成数据二义的问题。
例如:网络字节顺序采用大端的方式。
3.分类
1)大端(BE-Big endian):低地址存储高位
2)小端(LE-Little endian):低地址存储低位
例如:0x01020304
- 大端:01 02 03 04
- 小端:04 03 02 01
由此可见,字节序主要应用于存储单元大于一个字节的数据类型。(如果只有一个字节,那就一个字节一个字节的存储,不需要排序)
4.取决因素
主机字节序主要取决于CPU架构。
- X86 - 小端
- MIPS - 大端
5.如何编写程序分辨主机字节序?
首先,定义一个int类型的变量x = 1;
其次,我们知道int类型是4个字节的存储单元,所以可以再通过一个char类型的指针指向变量x;
此时,指针指向变量x的第一个字节(低地址)的内容,如果是00则是大端存储,如果是01则是小端存储。
#include<stdio.h>
void main()
{
int x = 1;
if (*(char*)&x == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}
二.整形数据的存储
1.整形数据在内存中的存储采用补码的形式
1)原因
- 保证了0的唯一性,保证了数的表示的准确性。
- 让加减可以统一处理,优化了数的运算过程。
- 解决了自身逻辑意义的完整性。
2)补码的特性
补码为一个负整数(或原码)与其补数(或补码)相加,和为模。在补码的运算中,对一个整数的补码再求补码,等于该整数自身。补码的正零与负零表示方法相同。计算机底层不区分无符号数和补码数,可认为其运算全部当作无符号数处理。
补码使得符号位能与有效值部分一起参加运算,从而简化运算规则。使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。所有这些转换都是在计算机的最底层进行的,而在我们使用的汇编、C等其他高级语言中使用的都是原码。
2.原码、反码、补码
- 原码(true form):将数字转换为二进制的定点表示方法。原码中第一位为符号位(即最高位为符号位):正数该位为0,负数该位为1,其余位表示数值的大小。
- 反码(Inverse code):将原码中的符号位不变,数值位取反。
- 补码(two's complement):反码+1。
例如:-10
- 原码:10001010
- 反码:11110101
- 补码:11110110
PS :
- 正数与无符号数据的原码、反码、补码是一样的,与原码相同。
- 在一些判断以及循环控制中,小心使用无符号数据,因为有符号数据与无符号数据进行运算的时候会产生隐式类型转换,将有符号数据转换为无符号的参与运算。
三.浮点型数据的存储
float存储数据的范围:~
1.小数在内存中以浮点形式存储
1)小数转换为二进制——乘2取整法
例如:
5.25——>101.01
浮点形式(类比科学计数法):
5.25——>1.0101*
2)存储标准(IEE754标准文档)
浮点数的表示分为三个部分:
- S-符号位,占据1个比特位
32位、64位——1个比特位
0—正数、1—负数
- E-阶码位(指数位),采用移码-1的方式来表示正负指数
32位—8个比特位,64位—11个比特位
- M-尾数,存放小数点后面的数值
32位—23个比特位,64位—52个比特位
3.移码
移码(又叫增码或偏置码)通常用于表示浮点数的阶码,其表示形式与j补码相似,只是其符号位用“1”表示正数,用“0”表示负数,数值部分与补码相同。
通俗的讲,因为指数位的数值有可能出现负数,但是指数域是无符号的,无法表示负数,所以要加上一个指数基数来表示,32位下的指数基数:127,也就是说,真正指数位存储的数据是实际数值+127(也就是移码-1)。
4.尾数
尾数就是小数点后面的数。
因为浮点存储在进行浮点移动时,总会移到第一个1的后面,因此所有数都会表示为"1.xxx...",所以可以只显示尾数部分,也就是不显示小数点前面的那个"1","1"就不用存储了,用的时候再加上,这样就可以节省一个比特位。
5.两种特殊情况
E全为0:这时候真实指数数值是1 - 127 = -126,M表示真实值,通常用于表示0。
E全为1:这时候真实指数数值是255 - 127 = 128,M为全0时,通常用于表示无穷大。
6.举例
-3.125
二进制:-11.001
S——1
E——1 + 127 = 128——>10000000
M——1.001
得到:1 10000000 10010000 00000000 0000000
即:11000000 01001000 00000000 00000000
即:c0 48 00 00
五.小结
虽然我们平时学习更注重代码的逻辑性,但是了解数据是如何在内存中存储的也是很重要的,只有懂得基本的框架,才能在此基础上更好的掌握和理解知识。
PS:如果你觉得有帮助那请你点个赞支持一下作者8~
若存在错误或你有一些想法,请多指教!