目录
一、整数
1.1 整数在内存的储存
整数在内存中存储是以二进制的形式存储的,而二进制又是以补码的形式存放的(因为cpu只能计算加法),对于补码这个最主要是针对负整数存储而产生的。正整数的原码、反码、补码都是一样的,这里的原码就是,一个数的二进制原码;反码是符号位不变其他数按位取反;补码就是以反码为基础来加一;注意这里原反补码注意针对负整数(因为正整数原反补是相同的)。
1.2 大小端字节在内存中的区别
为什么会有大小端:对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
大端:是指高位字节数据存储到低地址上,低位字节数据存储到高地址上。
小端:是指高位字节数据存储到高地址上,低位字节数据存储到低地址上。
这里的据一个例子,用1234这个数,1是高位字节数据,4是低位字节数据(这里的高低位可以理解成数字单位如千位高位字节数据,个位低位字节数据)。
注意这里只是存储时才是这样子存储,而打印时是按照你写的打印%x的比如上面的例子(0x表示16进制)打印11223344。
1.3练习案例
1 判断大小端:
#include<stdio.h>
int check_sys()
{
int a = 1;
if (*(char*)&a == 1)//先取地址才能读取内存,再取一个字节(强制char*)再解析那个内存的值
{
return 1;
}
else
{
return 0;
}
}
int main()
{
if (check_sys() == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
2 理解内存中存储
#include<stdio.h>
int main()
{
char a = -1;
//a存储过程中整型提升
//10000000 00000000 00000000 00000001原码
//11111111 11111111 11111111 11111110反码
//11111111 11111111 11111111 11111111补码
//实际存储为 11111111
//打印整型提升补符号位
//11111111 11111111 11111111 11111111原码
//10000000 00000000 00000000 00000000反码
//10000000 00000000 00000000 00000001补码
//这就是最终打印的结果,进制转换为10进制
signed char b = -1;
//和上面同理两个都是有符号数
unsigned char c = -1;
//到这里就不一样了,这是无符号数
//10000000 00000000 00000000 00000001原码
//11111111 11111111 11111111 11111110反码
//11111111 11111111 11111111 11111111补码
//实际存储也是11111111
//打印就不一样了,打印时也需要整型提升
//无符号整型提升是补0
//00000000 00000000 00000000 11111111原反补码
//答案为255
printf("a = %d ,b = %d, c = %d", a, b, c);
return 0;
}
补充说明一下整型提升概念,整型提升是打印时就会整型提升(提升为int类型字节个数也就是32比特位),整型提升分为2类,一类是对于无符号整型:无符号整型是在最前面补0。另一类是对于有符号整型:有符号整型是在最前面补符号位。
3 练习题目
#include<stdio.h>
//x86环境 小端字节序
int main()
{
int a[4] = { 1,2,3,4 };
int* prt1 = (int*)(&a + 1);
int* prt2 = (int*)((int)a + 1);
printf("%x,%x", prt1[-1], *prt2);
return 0;
}
在这个模拟内存图中答案就一目了然。
二、浮点数
2.1 浮点数在内存的存储
浮点数在内存的存储就和整数不一样了,整数是最好理解的,而在浮点数中,浮点数存储就有点抽象了,他是按照一个公式来存储的,V = (−1)^ S ∗ M ∗ 2^ E,这里需要理解(-1)这个上面的s表示是二进制中符号位(因为二进制中1表示负数,0为正),所以这里(-1)^S表示的也是符号位,这里的M*2^E整体表示的是科学计数法,而这里也是以二进制来计算,2为底数,E为指数,0<M<2的数,中M最前面的1不计算进去因为是确定的值,主要是小数点是最后23个比特位来表示(最前面的1不在23个比特,为了节约比特取确保精度)而E这个表示是中间的剩下的8个比特位来表示指数。
如图所示:
float
double
如:-5.0,浮点数存储时安排1(S) 1000 0000(E) 000 00000000 00000000 0101(M)
浮点数为(-1)^0(值符号位)*(二进制计算结果)*(E的实际值+中间数(127或者1023))。为啥要加中间值呢,因为E的实际值会有负数。
2.2 练习案例
#include<stdio.h>
int main()
{
int n = 9;
float* pFloat = (float*)n;
printf("n的值为,%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
*pFloat = 9.0;
printf("n的值为,%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
}
这里我们已经知道了整数储存和浮点数储存是不一样的,所以,这里答案为9,0(这里是整型9,内存中存储中E为0,2^0约等于0了),很大一个数(有效数字M等于001后⾯再加20个0,凑满23位,指数E等于3+127=130, 即10000010),9.0