接上回,让我们看看下个例题:
![](https://i-blog.csdnimg.cn/blog_migrate/9e857b7856eff45ab80332ab8d620f15.jpeg)
例4:首先,我们先写出-20的原码反码补码
原码:10000000000000000000000000010100
反码:11111111111111111111111111101011
补码:11111111111111111111111111101100
10的原码反码补码:
00000000000000000000000000001010
两个补码相加:
11111111111111111111111111101100
00000000000000000000000000001010
11111111111111111111111111110110(结果的补码)
因为输出结果是%d,是输出有符号的十进制数,所以要先将结果转化为原码,然后再输出。
(结果的补码)11111111111111111111111111110110
(结果的反码)11111111111111111111111111110101
(结果的原码)10000000000000000000000000001010 = -10
所以最终输出结果为-10.
![](https://i-blog.csdnimg.cn/blog_migrate/d3c6cfbaa83ef3c70c1c20467c454369.jpeg)
例5:
![](https://i-blog.csdnimg.cn/blog_migrate/4ddcaeea317c26f5da0b4195f8aaaa56.jpeg)
题中条件为(i=9;i>=0;i--)
解题思路:因为题中的i为int型且为无符号数,所以i永远都大于0,且打印要求为%u无符号十进制数。当i一直--,直到i<0时,由int型的范围可知,-1将被自动转化为一个很大很大的数(类似上一节char中的那个循环圈),所以i>=0,无限循环。因此打印结果为 9 8 7 6 5 4 3 2 1 0,很大的数......
![](https://i-blog.csdnimg.cn/blog_migrate/2ef953b9ae6df1919c55c8ffe58cbcc7.jpeg)
解题思路:有符号的char类型的范围为-128——127,共256个字符。strlen遇到‘\0'自动停止,0的ASCLL码值为'\0'。
由题意,char中存储的值为-1到-1000,由于char类型最多只能存256个字符,因此当存储的数值大于127或小于-128时,会被自动转化为-128到127中的值。例如,这题a[i]等于-128时,下一位为-129,但char类型中并没有-129,所以根据上部分的那个循环,将a[i]自动变为127,直到遇到'\0'才停止,因此最终结果为255。
例7:
![](https://i-blog.csdnimg.cn/blog_migrate/9303b2226c8b03de6cbdb02cf5b812bb.jpeg)
解题思路:无符号的char只能存0到255的数,所以当i=255时,i++之后便又开始了轮回,因此结果为无限循环打印hello world。
例8:
![](https://i-blog.csdnimg.cn/blog_migrate/a594adb04b9df8a769cbb07b4630f619.jpeg)
1E10表示1×10^10。
![](https://i-blog.csdnimg.cn/blog_migrate/9eba3b08e671219bdcdf1c540f83ed5e.jpeg)
让我们一起看看这串代码:
首先定义一个int n ,将n的地址放入float*指针中,再将&n强制类型转换成float型。按照我们的惯性思维,第一个printf应该打印出9,第二个应该9.000000,第三个应该是9,第四个是9.000000。那么结果是否是这样呢?让我们看看结果。
![](https://i-blog.csdnimg.cn/blog_migrate/5fb704cd9fa811d6b10775d1cecbe196.jpeg)
看来结果不如我们所愿,那这是为什么呢?这就要提到float在内存中的存储。
![](https://i-blog.csdnimg.cn/blog_migrate/5e85e80d0fbbe397ceef273f1208e977.jpeg)
如上图,任何一个二进制浮点数都可以写成(-1)^s *M*2^E
例如:5.5
写成以上表达形式就是 ( 101.1 = 5.5(.1 = 1*2^-1 = 0.5))
(-1)^0 *1.011*2^2
s = 0;
M = 1.011;
E = 2;
![](https://i-blog.csdnimg.cn/blog_migrate/50c8c9a807d88c13f8c8112a503af350.jpeg)
单精度浮点数存储模型:第一位符号位(s),后面8为给E,最后23位给M
双精度浮点数存储模型:第一位符号位,后面11为给E,最后52位给M。
特别注意:E也有自己的存储形式
![](https://i-blog.csdnimg.cn/blog_migrate/08c4f006fffc3af431e5ea4b13d0a8a7.jpeg)
简单来说,对于8位的E,中间数为127.对于11位的E,中间数为1023.
特别地:M在储存时只保留小数部分,如1.01,只保存01,自动舍弃1,最后再添上即可。
上面的5.5用二进制形式则表示为:
0 10000001 011 000000000000000000000
s E M(自动舍弃1) (因为M占23个bit位,所以后面自动补齐0)
将以上二进制转为16进制,查看其在内存中的存储:
0x40b00000
![](https://i-blog.csdnimg.cn/blog_migrate/e4bb6e96bf4ec54b0e25635b962fb318.jpeg)
接下来是E的几种特殊形式:
![](https://i-blog.csdnimg.cn/blog_migrate/8a3617e0c8909f75cb46b32de65b85dc.jpeg)
记住即可。
文章的最后,让我们再次计算刚开始的那道题目:
![](https://i-blog.csdnimg.cn/blog_migrate/5fb704cd9fa811d6b10775d1cecbe196.jpeg)
首先第一个打印int n = 9;打印有符号十进制整形,结果还是9
第二个,首先写出9的补码0 00000000 00000000000000000001001
E为全0
所以还原为浮点数表达式:(-1)^0*0.00000000000000000001001*2^-126
打印结果为0.
第三个,首先将9.0写成浮点数表达式:
(-1)^0*1.001*2^3
0 10000010 00100000000000000000000
符号位0表示正数,所以原码反码补码相同,直接打印即可,结果为1091567616
第四个结果为9.0
因此,若打印的值为整形,且以整形的方式打印,则没问题。若以浮点数方式打印,则有问题,反过来也一样,因此,浮点型与整形在内存中的存储方式是不同的。