5.输出是什么?
int main() { unsigned int i; for (i = 9; i >= 0; i--) { printf("%u\n", i); } }
结果在不断的往下打印:
注意unsigned无符号数都是>=0的,unsigned int能放下的最大二进制序列是
11111111 11111111 11111111 11111111
对应的十进制数字是4294967295
当i=0时,0-1=-1
-1的原码
10000000 00000000 00000000 00000001
反码
11111111 11111111 11111111 111111110
补码
11111111 11111111 11111111 11111111
✨如果-1存到一个无符号数的变量里面去,这个时候的最高位不是符号位,被当成一个无符号数来打印
✨在打印的时候,i是一个无符号型的变量,所以虽然里面放的是-1这样的一个值,但是站在i的角度,i里面不会放-1,他认为里面的每一个位都是有效位,是一个很大的数字,这个数字>=0.所以-1放到i这个变量里面,他不会认为是-1,而认为它是一个很大的数字.接下来再不停-1,就会出现很多数字
所以不管i里面放的是什么数,这个数恒>=0,for循环会进入死循环
5.变形(如果以%d打印,结果会怎么样)
✨也会一直死循环,但是可以打印出-1
✨因为在for循环的判断条件,i是无符号类型,所有的位都是有效位,i>=0条件恒成立会进入死循环
✨可以打印出-1是因为打印的时候以%d有符号数的形式打印
6.输出是什么?
int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d", strlen(a)); return 0; }
详解:
这个循环肯定循环1000次
strlen统计的是\0前字符出现的个数
但是要注意的是✨✨✨
a数组里面的每个元素都是char类型,char的取值范围是-128~127,那么数组元素可以放-1000这样的数字吗?
当a[i]是-128时,二进制序列再-1的时候,就会变成127,不会是-129(如上图箭头的指向)
7.输出是什么?
#include <stdio.h> unsigned char i = 0; int main() { for(i = 0;i<=255;i++) { printf("hello world\n"); } return 0; }
注意:
循环变量用无符号数控制的时候要小心注意啦!
详解:
3.浮点型在内存中的存储
常见的浮点数
3.14159 字面浮点数
1E10 科学计数法表示的浮点数,意思是1.0*10^10
浮点数家族包括:float,double,long double类型
整型家族的类型的取值范围:
limits.h中定义
查看limits.h文件:
浮点数表示的范围
float.h中定义
3.1 浮点型存储的例子
int main() { int n = 9; float *pFloat = (float *)&n; printf("n的值为:%d\n",n); printf("*pFloat的值为:%f\n",*pFloat); *pFloat = 9.0; printf("num的值为:%d\n",n); printf("*pFloat的值为:%f\n",*pFloat); return 0; }
详解:
3.2 浮点数存储规则
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
✨(-1)^S * M * 2^E
✨(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数
✨M表示有效数字,大于等于1,小于2。
✨2^E中的E表示指数位。
10进制的5.5转换成二进制数字是多少?
是101.1
这个数字用科学计数法表示,小数点向左移动
1.011*2^2
第一个2是因为二进制的权重是2,第二个2是因为移动了两位
V=5.5
=1.011* 2^2
=(-1)* 0 *1.011 * 2^2
这里的S=0,M=1.011,E=2
所以只需要把S,M,E这三个数字存起来,就能把原来的浮点数还原出来
浮点型二进制序列空间划分
float 32位的浮点数
double 64位的浮点数
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
浮点数数据具体是怎么存进去的呢?
有效数字M
有效数字M,实际上在存储的时候,只存小数点后面的位.当往出拿的时候,拿出小数点后面的位,在小数点前面补个1就能还原出M真实的值.
单精度浮点数,双精度浮点数中的精度表示小数点之后的位存的更多,精度更高.(小数点后存的位是二进制位)
✨当存小数的小数点后面的部分时,二进制位可能会为了凑够小数部分而不断的向后扩张,那么对于可以存放23位小数部分的单精度,可以存放52位小数部分的双精度真的够吗?
🤞可能会不够,所以说也有一些浮点数在内存中是不能够精确保存的.
指数E
首先,E为一个无符号整数(unsigned int)
1.这意味着,如果E为8位,它的取值范围为0~ 255;如果E为11位,它的取值范围为0~2047。
2.但是,我们知道,科学计数法中的E是可以出
现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,3.
对于8位的E,这个中间数是127;
对于11位的E,这个中间数是1023。
比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001
(所以即使我的E是负的,经过修复之后变成正的值,这个时候就可以存到E里面去了)
举例说明
打开内存验证一下浮点数f在内存中存的是什么
解决疑惑
如果E是-130,+127之后认识负数怎么办呢?
🤞float也是有它的取值范围的,就不会让真实的E是-130的.
🤞如果E=-130的话,已经超出float能够表示的最大值和最小值了.所以在能够讨论的范围内讨论.
浮点数怎么从内存中取出来呢?
指数E取出来,分为三种情况:
(1)E的部分不全为1或者不全为0
这是一种常规情况,怎么放进去就怎么倒着拿出来
(2)E全为0
E全为0,说明原来的E加上127之后为0,原来的E是-127,原来的浮点型数据是一个非常小的数据
这个数据是 ± 1.xxx *2^(-127)
这个数据是接近于0的非常小的数字
(3)E全为1
8个比特位全为1的话就是255,这是加了127之后,原来的E是255-127=128
1.xxx*2^128 z这将是一个非常大的数字
在加上最前面的符号位±,表示的就是±无穷大的数字
3.3 分析3.1中的例题
详解
总结
数据的存储内容全部总结到这里啦,如果对小伙伴们有所帮助的话,可以点赞收藏博客,关注后续的C语言学习内容哦~😉👻👻