这几天在重新学习C语言,也是学习到了一些以前学C的时候老师没讲自己也没学到的东西【持续更新】
作者:互联网
先说明一下,我荒废了一个寒假,开学以来不知道自己应该学点什么,马上就要实习了,不知道自己的目标,想学习数据结构和算法,但是迟迟下不了手去写代码,又想写一个Android原生的项目,但是对JNI不熟悉,如果要学JNI,那我的C语言就要拿出来,基础语法倒没什么问题,当时是教到结构体就期末了,后面分配内存回收什么的都没教,也没去学,之前自学make和cmake也稍微入门,但是我总觉得对C的学习不够透彻。于是就把CPrimer拿出来看看,在这里记一下学习过程中印象深刻的地方。
2022.03.25
我对C的了解并不深,然后就是学习到CPrimer这本书的float型数据这里,书上讲了float型数据的保存方式,float占4个字节,尾数24位,而符号位和阶码共占8位,包括FLT_MANT_DIG这个float.h文件都表示float的尾数是24,我就想到了学习计组的时候那个IEEE754的标准,当时花了2小时左右的时间看了计组的那部分,然后写了如下的程序
float f = 3.5f;
char *s = &f;
printf("%d ",s[0]);
printf("%d ",s[1]);
printf("%d ",s[2]);
printf("%d \n",s[3]);
//输出的结果是 0 0 96 64
/*根据书里对float的描述和IEEE754的标准,我算出来是这样
* 3.5(10) = 11.1(2) = 1.11*2^1
* S = 0,E = 1+63(63其实不对)M = 11000000 ....
* 即 01000000 11000000 00000000 00000000 这个结果现在看挺可笑的,我混淆了字节的64和E的64,算错了两个地方还草草地下了一个结论表示float不是IEEE754标准
* 正确应该是这样
* S = 0,E = 1+127 M = 11000000 ....
* 即 01000000 01100000 00000000 00000000
* 我是如何验证的呢?我搞了一个4.5
* 4.5(10) = 100.1(2) = 1.001*2^2
* S = 0,E = 2+127 M = 00100000 ....
* 即 01000000 10010000 00000000 00000000
* 那事实上就是C的float的保存方式是IEEE754的标准
*/
然后就是float这个数据的物理上的高位字节反而是在草纸上计算出来的逻辑上的低位字节,结合了double型数据8位的数据,我就猜到了,高精度转低精度的时候,是把物理上高位的字节截掉,高位字节是尾数的尾部嘛,被截掉精度就丢失了,这就是double转float精度丢失的原因,但我还是想不通为什么FLT_MANT_DIG是24。
/*还是3.5这个例子
double的3.5:
逻辑上:01000000 01100000 00000000 00000000 4[00000000],从第2个字节的第2位开始是尾数
物理上:4[00000000] 00000000 00000000 01100000 01000000,直到倒数第3个字节和第2字节除第1位外都是尾数
float的3.5:
逻辑上:01000000 01100000 00000000 00000000,同double
物理上:00000000 00000000 01100000 01000000,同double
所以,double转float就是把double前4个字节截掉,因为前4个字节在物理上是尾数部分,所以去掉就丢失了尾数的精度
*/
接下来是int数据
int i = 1;
//经char*后输出来是1 0 0 0
//00000001 00000000 00000000 00000000 同样是物理上的高位字节是逻辑上的低位字节
int j = -1;//-1 -1 -1 -1
//11111111 11111111 11111111 11111111 也就是说int采用的是补码作为它的保存方式
unsigned int *k = &j;//*k的值是4294967295,即unsigned int的最大值
标签:学到,尾数,字节,00000000,double,float,重新学习,C语言,01000000 来源: https://www.cnblogs.com/thankvincisdaily/p/16052885.html