对于C语言,数据类型有如下几种:
这些类型也是这后要一一去学的,今天只讨论基本数据类型,主要是数据范围相关的问题。如下有一张表来概述基本数据类型,这里先贴出来,目的不是背下来,而是接下来会对其进行分析:
下面对于char类型的数值范围进行分析,上篇博文学习了补码的知识,这个就很容易就能理解了:
对于八位二进制,计算机存储是以补码的形式,所以:
最大数应该是:01111111【正数】=127
最小数应该是:10000000【负数】=-128
理解了这个类型的数值取值范围,表达其它类型也就以此类推了。从中可以发现补码的知识对于理解C是有一定的帮助的哟。
清楚了类型数值的取值范围,下面就以代码的形式来进一步分析数据类型,从程序打印中会有很多难以理解的,但我们有了补码的知识后,其实也不难了;
首先从程序中打印数据类型的长度,以验证图中说的看是否一致:
打印结果:
下面就要分析一系列比较奇怪的输出结果了,但是最终都是有据可依的,并非这些值打印都是乱打印的:
分析一:
输出结果:
第一个输出毫无疑问,原样输出。
而第二个输出原因如下:
-1的补码是全1【如果不清楚的可以看博文学c从认识计算机的数据表示开始 - cexo - 博客园】
而整数常量是四个字节,用十六进制表示:FFFFFFFF,而它的十进制数为:
无符号输出就为上面这个庞大的值啦,不足为奇了吧!
分析二:
输出结果:
① printf("%d\n",128);输出结果:128
这个毋庸置疑,以正常的十进制输出,就不多解释了。
② printf("%hhd\n",128);输出结果:-128
128的二进制数为:10000000
由于它是以一个字节显示,也就正好是八位,所以输出的值就为10000000,而
补码10000000的值就是为-128,所以这就是原因所在。
③ printf("%hd\n",128);输出结果:128
128的二进制数为:10000000
由于它是以两个字节显示,也就正好是十六位,所以输出的值就为0000000010000000,而
补码0000000010000000的值就是为128,所以这就是原因所在。
④ printf("%hu\n",128);输出结果:128
从第③点来看,既使是无符号的,最终值也是128
分析三:【这个就不是那么好理解了,但也有机可寻!】
输出结果:
下面一一对其进行分析:
① printf("%d\n",ch);输出结果:-128
由于%d是按四个字节的十进制输出,而ch是char类型,只占一个字节,所以这里涉及到一个新的知识:符号位扩展
char类型的128的二进制数为:10000000,而输出是需按四个字节,所以这时计算机会将符号位1进行扩展成四个字节,也就是在前面多加了24位1
这个数补码实际上就等于-128,为什么呢?下面为了说明问题,用一个稍小一点数来分析:
明白了这个,下面几句的打印就都比较好理解了。
② printf("%hhd\n",ch);输出结果:-128
char类型的128的二进制数为:10000000
由于它是以一个字节显示,也就正好是八位,所以输出的值就为10000000,而
补码10000000的值就是为-128,所以这就是原因所在。
③ printf("%hd\n",ch);输出结果:-128
char类型的128的二进制数为:10000000
由于它需以两个字节输出,也就是十六位,所以这时计算机会将符号位1进行扩展成四个字节,也就是在前面多加了八位1,所以输出的值就为1111111110000000,而
补码1111111110000000的值就是为-128,所以这就是原因所在。
④ printf("%hu\n",ch);输出结果:65408
char类型的128的二进制数为:10000000
由于它需以两个字节输出,也就是十六位,所以这时计算机会将符号位1进行扩展成四个字节,也就是在前面多加了八位1,所以输出的值就为1111111110000000,而
补码1111111110000000无符号的值用十六进制表示为:ff80,对应的十进制数为
用程序打印一下看是否是如图上所说:
运行结果如下:
对于C语言类型的选择,有下面一个简单的原则:
1. 如果没有特殊需要,浮点数总采用double 类型,因为它的精度和表示范围能满足一般要求(float的精度常常不够,long double 可能降低效率)。
2. 如果没有特殊需要,整数总采用int 类型,因为它是每个C 系统里的最基本类型,必定能得到硬件的基本支持,其效率不会低于任何其他整数类型。
3. 如果没有特殊需要,字符总采用char 类型。
4. 尽量少用各种unsigned 类型,除非服务于某些特殊目的。
数值常量后缀:
整数:123 075【这是八进制表示法】 0xA8 123U 95538L
双精度浮点数:123.5 0.8 .003 2.45E17 105.4e-10
单精度浮点数:1.3F 1.783E-3F
长双精度浮点数:3.417E34L 3.5L .05L
可见浮点数是不精确的,要想表示更大的数,可以用科学技术法:
float最大值为:3.4x10^38,如果超过了这个值会怎么样呢?
编译就报警告了:
这时运行输出就会乱了:
这时为了能容下这个超double范围的数,就只能将其变为long double了:
这时输出,就可以看到无比大的浮点数了:
输出就不正常了:
建议:输出long double类型,用"Lf"
好了,关于数据类型的学习就到这,里面还是有很多值得细细揣摩的,下回见!
关注个人公众号,获得实时推送