C语言系列
【C语言】函数
【C语言】选择语句和循环语句
【C语言数据类型,变量和常量】
前言
前面我们学习了C语言的内置数据类型,今天让我们从内存的方面深度学习一下整形和浮点型在内存中的存储。
一、整形在内存中的存储
整形家族:char, short, int, long, long long 等
整形的表示范围:limits.h中定义
1.原码、反码、补码
计算机中的整数有三种表示形式,原码,反码和补码。
这三种表示形式均有符号位和数值位组成,符号位表示在最高位比特位上。‘1’表示负数,‘0’表示正数。
我们知道一个int的大小是4个字节,32位比特位,所以从左往右的第一位便是符号位,其他位都是数值位。
正整数的原码,反码,补码相同。char类型存储在内存中的是对应的ASCII值。
负数的原码,反码,补码各不相同。
原码:直接将数值按照正负数的形式翻译成二进制就可以得到原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。内存中存的是补码!!
#include <stdio.h>
int main()
{
int i = -1;
//负数的符号位为1
//原码:1 0000000 00000000 00000000 00000001
//符号位不变,其他位按位取反
//反码:1 1111111 11111111 11111111 11111110
//取反后+1
//补码:1 1111111 11111111 11111111 11111111
return 0;
}
32位的‘1’,在内存中以16进制展示出来就是 0xff ff ff ff。
这时候可能有同学会问:为什么要在内存中存补码呢,为什么不存反码呢?
使用补码,可以将符号位和数值域统一处理。
2.大端存储和小端存储
2.1什么是大端存储和小端存储
对于有2个字节及其以上字节的变量,在内存中存储是有许多种存储方式,但有两种存储方式最常见。
大端存储:数据的低位字节序的内容保存在内存的高地址中,而数据的高位字节序的内容保存在内存的低地址中。
小端存储:数据的低位字节序的内容保存在内存的低地址中,而数据的高位字节序的内容保存在内存的高地址中。
2.2如何确定大小端
取出n的地址,强制类型转换成char*,再解引用操作访问之后的一个字节,以此判断大小端。
二、浮点型在内存中的存储
浮点型家族:flaot, double等
整形的表示范围:float.h中定义
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
举个栗子,在生活中使用10进制的科学计数法时,
如图所示,当浮点数位9.0时 S=0, E=3, M=1.001。
IEEE 754规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
S:
S为‘1’表示负数,为‘0’表示正数。
M:
前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。(保存时舍去第一位的1,读取时再加上第一位的1)
这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
E:
首先,E为一个无符号整数。这意味着,如果E为8位,它的取值范围为0-255;如果E为11位,它的取值范围为0~2047。
但我们知道科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。(保存时加一个中间数127/1023,读取时减去这个中间数)
指数E从内存中取出还可以再分成三种情况:
1.E不全为0或不全为1:E减去中间值,M前加上第一位的1。
2.E全为0:E=1-中间值,M前不加第一位的1。
3.E全为1:这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)
总结
以上就是今天所讲的内容,如果对你有帮助的话,请点个赞,我们下次再见。