我们已经学到的数据类型有浮点形和整形那么它们是怎么存储的呢?

目录

整形

整形成员

存储方式

源码反码补码

源码反码补码的关系

整形数据的使用

整形提升

是什么

怎么提升呢?

哪种情况提升呢?

浮点型

浮点型成员

存储方式

存储补充

浮点数的使用

整形

整形成员

首先我们来看一下整形家族有哪些,整形家族有:int 、long  、long long、其实char也是整形的一员,其代表所表示的字符的ASCII码值。

存储方式

看一下以下代码:

int a = 10;

char b = 10;

这里由10是一个整数,代表一个int类型的数据,换算成二进制数则有32位数,如下:

000000000000000000000000000001010

然后要存入变量a对应的内存块,这里有一个规则,存入的时候要以补码的形式存入

源码反码补码

源码反码补码的关系

源码变成反码,符号位不变其它位按位取反。反码变成补码,反码加一就是补码。

为什么要用到补码这个东西,它的优势何在?

这里插一句题外话:由于处理器中只有加法运算器,故当涉及减法或者负数加减的时候,这个时候使用补码就有优势了,首先我们怎么去理解补码这个东西呢?看一下以下的图

以上是char类型的(八位)的补码对应的值,如用补码进行计算1-2,则只要用加法器进行加上1和-2分别对应的补码就可以,即

00000001+11111110,得到11111111,在换成源码就对应了-1.由此可见利用补码的优势。(这里用时钟来理解也可以,本质上是一样的)

好,回归正题。

上面讲到要用补码来进行存储,但是这里会遇到一个问题,就是10这个数字是int类型的默认为其有三十二位(000000000000000000000000000001010),但是char类型的内存容量只有八个bite也就是说只能容下八位,故会截断后存储(00001010)。

整形数据的使用

整形数据的使用,int 类型当然是按存的补码转换成源码来用,但是如果是char类型的时候,会有整形提升这个东西,那什么是整形提升呢?

整形提升

是什么

整形提升简单来说就是由于处理器中的运算器有三十二位,在使用的数据类型少于三十二位的时候会自动变成三十二位,这里一般对象为char或者short类型的变量。

怎么提升呢?

整型提升的一般规则为:首先先判断是否为有符号位(即是否为signed类型),如果是unsigned则在前面补上0,补到32位为止,如果是signed的话就要继续判断符号位,如果符号位为1则前面不上1补到32位,如果符号位为0则前面补上0补到32位。

哪种情况提升呢?

一般情况为,加减乘除,这样的算数运算(如+a,-a,1*a,1/a),位运算(>>a,<a,=,==),使用函数printf("%d",m);这些时候就会进行整形提升,让短整型变成int 类型的长度。

例子:

#include

int main()

{

char m = -1;

printf("%d\n",sizeof(m));

printf("%d\n", sizeof(+m));

printf("%d\n", sizeof(-m));

printf("%d\n", sizeof((char)1 * m));

printf("%d\n", sizeof((char)1/m));

return 0;

}

这里就发现确实有这么一回事,让我们继续看一眼下面的例子:

#include

int main()

{

char m = -1;

printf("%u\n",m);

printf("%d",m);

return 0;

}

这个是为什么呢?

我们来看看,首先这里是会整型提升的,然后我们在进行分析,首先,-1对应的int 类型的反码为:

11111111111111111111111111111111

存入char之后,截断成:

11111111

在使用整形打印的时候,会发生整形提升,由于本编译器中char为signed类型的,故提升为:

11111111111111111111111111111111

其对应的源码为:

1000000000000000000000000001

这个时候看是把它看成什么,如果是有符号数(”%d“)则为-1,如果是无符号数(”%u“)则为一个很大的数(最高位不是符号位)。

我们继续看下面的例子:

#include

int main()

{

char m = -1;

unsigned char n = -1;

printf("%u\n",m);

printf("%u\n",n);

printf("%d\n",m);

printf("%d\n",n);

return 0;

}

这里我们分析一下,unsigned char类型,同样,存入-1的时候都是一样的截断,故存入的数据为:11111111

在用无符号数打印时,同样发生整形提升,由于是unsigned类型的,故前面补上0,得到:

000000000000000000000000111111111(由于是正的,故源码反码补码相同)

这里用无符号数打印的话,就是255,如果用有符号数打印的话,还是255。

到这里整形的存储和使用就讲完了,接下来就是浮点数的存储和使用了。

浮点型

浮点型成员

浮点数的成员有:float ,double ,long double

存储方式

浮点数的存储方式与整形完全不同。

要了解浮点数的存储方式,我们先要了解科学计数法,对于十进制的科学计数法我们很熟悉,如31415.926用科学计数法表示就是(-1)^0*3.1415926*10^4,好这样我们类比到二进制的科学计数法,100101.1001,这里我们可以表示为:(-1)^0*1.001011001*2^5,这里的参数(注意这里有一个点,就是由于有效数字前面总会是1,故省去不写,剩余的存入,存入提供的空间为23,不足时后面补0)1.001011001,0还有5就是浮点数类型要存储的数据。IEEE754标准提供了存储的方式,float的存储方式为:

前面第一位就是-1的指数,中间的八位为2的指数位,后面为有效数字。

这里有一个例子:

#include

int main()

{

int a = 10;

float* p = (float*)&a;

printf("%d\n",a);

printf("%f\n",*p);

*p = 10.0;

printf("%f\n",*p);

printf("%d",a);

return 0;

}

第一个毋庸置疑,第二个我们来看一下:

由于a变量对应的内存块中存入的是:00000000000000000000000000001001

强制类型转换成float*并且解引用后,会把他当成浮点数来看,那么为什么是0呢?这里就涉及浮点数的存储和使用了。

存储补充

存进去的时侯,如果2对应的指数为负数的话,那么这里就无法直接存储了,因为这个只能存储正数,故IEEE754规定,2对应的指数存入的值等于真实值加上127.

浮点数的使用

浮点数的使用,按照IEEE754的规定来将浮点数对应的内存块取出来,然后转化成对应的数值,这里有两个值得注意的点,由于有效数字对应再存入的时候少了第一位1,故看的时候要加上,还有,这里的2的指数这里要分情况看,如果是0的话,结果就是0(由于减去127,这里是一个很小的数字,由于表示的位数有限,则直接为0)如果全为一的话,则是无穷大(同样的道理),如果是其他的数的时候就减去127,得到指数部分。

故上面

00000000000000000000000000001001

这里2的指数部分全为0,则结果为0

利用指针将a改为10.0时,用浮点数指针打印出10.0这个没问题,但是用整形打印出来就变成了一个很大的数,为什么?

在让我们分析一下,

10.0这里可以写成科学计数法:(-1)^0*1.0*2^1

这里存入的数据为0,1+127,0

即010000000000000000000000000

发现转换成十进制就是上面的数。

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: