char属于整型家族是因为字符在内存中存储的是它们的ASCII码值,ASCII码值0-127均为整型。
注:对于short int、int、long int而言,有标准定义了它们均为signed默认有符号:
但是对于char字符型而言,并没有规定char与signed char能划等号,char与signed char的关系取决于编译器,不能盲目划等。因此此处应注意。
void表示空类型(无类型),通常用于函数的返回类型、指针类型以及函数的传参:
整型数据一般以其二进制序列补码的形式存储在内存当中。
对于正整数而言:它们的原码反码补码相同。
对于负整数而言:原码直接求出;反码为原码符号位不变、其他位按位取反;补码为反码+1
那么就有疑问了:为什么要以补码的形式存储在内存中呢?原因是便于计算:
我们如果通过原码相加,计算结果是不正确的,而补码就能够得到正确答案,同时,对于减法而言,也可以将a-b转换为a+(-b)的形式进行计算,乘除其实实质上就是累加与累减。
我们也可以通过查看内存信息,来观察a、b在内存中的存储情况:
&a得到下图中结果:这里注意是十六进制显示的补码,且为小端字节序存储(下面讲)
&b得到下图中结果:同样为十六进制显示的补码,这里看不出大小端存储方式。
我们首先要讲清楚二进制与十六进制之间转换:对于二进制而言,每一位用0或1表示,那么同理,十六进制即为0-15:但是每一位不能用两位数所以后面的两位数便替换成了a、b、c、d、e、f。
我们知道十六进制每一位最大应该为15(16进位,15用f表示),在二进制中1111才能表示15。因此十六进制中每一位由二进制的四位构成。即十六进制每一位其实是4bit位、每两位代表一字节(因为二进制32bit位8字节)。因此在内存中我们才能看到十六进制表现形式上每两位放在了一起,如上图所示。
那么通过&b得到的十六进制数为ff ff ff ff就说明对应的二进制序列全1。而全1正是-1的补码,所以也从实际编译器内存中可以看出,数据在内存中存储的是对应二进制序列的补码形式。
大小端字节序指的是数据在电脑上存储的字节顺序(不是二进制序列顺序)。
首先,对于数据的进制序列表示形式,低位字节处在右,高位字节处在左。如下图:
理解了这一点,我们就能够理解大小端字节序存储的概念:
大端字节序存储:把一个数据的低位字节处的数据存储在内存高地址中,高位字节处的数据存放在内存低地址中;
小段字节序存储:把一个数据的低位字节处的数据存放在内存低地址中,高位字节处的数据存放在内存高地址中。
那么我们可以写一个代码来判断该编译器是小端字节序存储还是大端字节序存储:
我们在内存中查看一下:看看是否正确:a=1十六进制为0x00000001。
符合小端字节序存储。说明我们上面的程序没有问题。
在讲实例之前,我们要理清楚无符号类型与有符号类型的大小范围区别:
拿字符char型举例,如下图所示:
上述两个闭环,无论是顺时针还是逆时针都是正确的。
signed char取值范围在-128~127;unsigned char取值范围在0~255。
另外一点我们要清楚:
%d用于输出十进制有符号整数;꺃十进制无符号整数。
接下来看例子:
①输出-1,-1,255
②输出
(无符号输出为)
③输出
④输出-10
⑤输出死循环 9~0然后~0死循环
⑥输出255
⑦输出hello world死循环
如3.、2E5(表示2*10^5)等等
浮点型类型包括:float(单精度、32位)浮点型、double(双精度、64位)浮点型、long double
浮点数表示的范围在头文件float.h中定义。
上面我们了解了整型数据在内存中的存储模式,那么浮点型数据和整型数据在内存中的存储是不是一样的呢?我们通过一个例子来比较一下:由于int和float类型同是4字节32bit位,那么我们就拿他俩进行比较:
我们在VS上执行程序来查看一下结果:
我们发现,无论是将整型强制类型转换后输出浮点型的值,还是解引用浮点型指针取值后的原整型数据的值,都与我们心中所想的有非常大的区别:这就说明了,浮点型数据在内存中的存储与整型数据在内存中的存储是不一样的。
那么我们接下来就介绍一下浮点型数据在内存中的存储方式:
浮点型数据在内存中的存储方式由国际标准IEEE754规定:
单纯地这么看会觉得很麻烦,我们来举个简单的例子:对于5.5而言,S=0;M=1.011;E=2。
为何5.5十进制转换为二进制为101.1呢?如下图就能轻松理解:
IEEE754规定了32位浮点数和64位浮点数中S、M、E分别占的位数,
对于32位浮点数和64位浮点数而言:S均只占据首位;
32位浮点数:E占据中间8bit位,M占据剩下23bit位;
64位浮点数:E占据中间11bit位,M占据剩下52bit位。
IEEE754对指数位E和有效数字位M还有一些规定:
对于M而言:由于M最终表示出来通常为1.xxxxxxxx的形式,因此我们将M存放在内存中时一般只存M的小数部分,这样就可以节省一位空间。IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的小数部分。例如M=1.011,那么就只有011会保存在内存当中,剩余M的空位全部补0。
对于E而言:标准将其定义为无符号整数,32位浮点数里E的取值范围为0~255;64位浮点数里E的取值范围为0~2047。但是对于指数位而言,是可能出现负数的,因此标准中存入的E的值其实等于E的真实值加上127或者1023(32位浮点数加127、64位浮点数加1023)。例如,E=2时如果要保存成32位浮点数时,真正存入内存中E的8bit位中的值应该是2+127=129,转换为二进制(因为E无符号整型);如果要保存成64位浮点数,E存入值应该为2+1023=1025,转换为二进制存入内存。
对于从内存中取出E的情况:
当E不全为0或者不全为1时,就是一般情况,直接取出即可,E真实值=E存入值-127/1023。
当E全为0时,我们可以知道E真实值极小,对于一个指数值而言无限趋于0,这个时候的E真实值不再等于存入值-127/1023,而是等于1-127/1023,同时取出M中xxxxxxxx时小数点 . 前不再默认置1,而是置0:得到M应该为0.xxxxxxxx而非之前一般情况的1.xxxxxxxx。
当E全为1时,我们可以知道此数字±无穷大。
那么当我们理解了浮点型数据是怎么在内存中存储的时候,我们回过头来去真正地完成开始的例子:
同时,我们也想知道,*pFloat=7.0后,
存储在内存中的二进制序列000000000000000000000对不对呢?
我们转换为十六进制:80 e0 00 00
然后查看内存中pFloat的信息:
前面我们测试过:VS编译器下为小端字节序存储,这里再一次验证了。
那么我们发现,我们求得的十六进制和通过VS查看的这个32位浮点数7.0的十六进制保存形式是一模一样的,因此没有求错。
同时000000000000000000000的值也确实是。
那么以上就是数据在内存中存储的全部内容啦,我们梳理了数据的类型、整型数据在内存中的存储方式、浮点型数据在内存中的存储方式还有两者的一些区别和相互转换的底层逻辑,掌握以上内容,能对计算机底层对不同类型数据的处理有更深层次的认知。
到此这篇uchar是什么类型(uchar是什么类型数据)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/sjkxydsj/74412.html