习题2
#include <stdio.h> int main() { char a = -128; printf("%u\n",a); return 0; }
习题3
#include <stdio.h> int main() { char a = 128; printf("%u\n", a); printf("%d\n", a); return 0; }
这个跟前面的题一样都是先发生截断,然后整形提升,然后再打印
习题4
1. #include <stdio.h> 2. int main() 3. { 4. int i = -20; 5. unsigned int j = 10; 6. printf("%d\n", i + j); 7. return 0; 8. }
习题5 unsigned三码习题
1. #include<stdio.h> 2. int main() 3. { 4. unsigned int i; 5. for (i = 9; i >= 0; i--) 6. { 7. printf("%u\n", i); 8. } 9. return 0; 10. }
我们看到这里9-0都是正常打印但是到-1就出现了问题,具体原因请看下图
二进制下的32个1,换成十进制为一个特别大的数字,所以会打印4294967295,之后每次i--这个数都会减一
习题6 signed char取值范围问题
#include<stdio.h> #include<string.h> int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d", strlen(a)); return 0; }
这里把数字放入到数组a中,而a是char类型,范围为-128~127
这里是-1-i,其实就是上面这个图逆序的走法,从-1~-128~127~0
\0的ASCII码值是0,strlen遇到\0会停下来,所以在遇到0之前,数组里面已经存了128+127个数字了,所以打印255
习题7 无符号char取值范围习题
#include<stdio.h> unsigned char i = 0; int main() { for (i = 0; i <= 255; i++) { printf("hello world\n"); } return 0; }
程序运行后会进入死循环,这是因为i是unsigned char类型范围是0~255,前面有说过,i为255之后,i+1,此时i又变为0,陷入死循环
习题8 关于strlen返回值类型的习题
#include<stdio.h> #include<string.h> int main() { if (strlen("abc") - strlen("abcdef") >= 0) printf(">"); else printf("<"); return 0; }
这里会打印>是因为strlen返回值为unsigned int类型,无论怎样运算结果都>=0.
可点开这个链接,最后面有一道类似的题
浮点型在内存中的存储
浮点数家族包括: float 、 double 、 long double 类型。
浮点数表示的范围: float.h 中定义
用everything查找float.h然后用VS打开,就可看到浮点数的范围,整形输入litmits.h可查看范围
浮点数存储规则
根据国际标准 IEEE (电气和电子工程协会) 754 ,任意一个二进制浮点数 V 可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S 表示符号位,当 S=0 , V 为正数;当 S=1 , V 为负数。
M 表示有效数字,大于等于 1 ,小于 2 。
2^E 表示指数位。
举例来说:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。
那么,按照上面V的格式,可以得出S=0,M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2。
9.5f其实用二进制表示为:1001.1,这跟权重有关系,因为2^-1为0.5
1001.1=1.0011*2^3
S=0,M=1.0011,e=3
例:9.6f
二进制:1001.XXXXXX,因为这个0.6不好表示,需要一堆0和1,但是如果数字过多就有可能存不下,因此浮点数就产生了精度问题
float 4byte double 8byte
浮点数如何保存
IEEE 754 规定:
对于 32 位的浮点数,最高的 1 位是符号位 s ,接着的 8 位是指数 E ,剩下的 23 位为有效数字 M 。
特别规定:
前面说过, 1≤M<2 ,也就是说, M 可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。
IEEE 754 规定,在计算机内部保存 M 时,默认这个数的第一位总是 1 ,因此可以被舍去,只保存后面的 xxxxxx部分。
比如保存 1.01 的时 候,只保存01 ,等到读取的时候,再把第一位的 1 加上去。
这样做的目的,是节省 1 位有效数字。以 32 位 浮点数为例,留给M 只有 23 位, 将第一位的1 舍去以后,等于可以保存 24 位有效数字。
指数E的存放规则
首先, E 为一个无符号整数( unsigned int),这意味着,如果 E 为 8 位,它的取值范围为 0~255 ;如果 E 为 11 位,它的取值范围为 0~2047 。
如0.5=1.0*2^-1 M=1.0,E=-1,S=0
E为负数不在范围之内,所以 IEEE 754规定,存入内存时 E 的真实值必须再加上一个中间数:
对于 8 位的 E(float) ,这个中间数是127。
对于 11 位的 E(double) ,这个中间 数是 1023 。
刚才E=-1,按float类型,E+127=126,把126存放到E所在的空间当中(8个bit)