疑难问题:类型转换
类型转换有两种:
区别,在于显示使用强制转换运算符进行转换,是有种醒目方便的类型转换方式,隐式转换则是遵循一定规则,在表达式或者语句中解决类型不匹配的问题的解决形式。
表达式中的类型转换按照功能具体划分的话,分为升级和降级(粗略划分,主要讲的是在表达式中),比如int–>char是降级,int–>float为升级,他们的级别顺序依次由高到低为:
long double、double、float、unsigned long long、long long、unsigned long、long、unsigned int、int、short、char。
这里不讨论复杂的类型转换,只讨论基础类型转换。
转换原则:
1.当类型转换出现在表达式中,char和short自动转换为int,因为char和short是最低级,直接转换为int类型,称为升级,比如unsigned short范围为0~65535,unsigned char的范围为0~255,那么:
unsigned short a = 65535;
unsigned char b = 100;
int c =0;
unsigned short e = 0;
c = a + b; 第5行
e = a + b; 第6行
printf("c=%d\nd=%d",c,e);
结果为:
c=65635 d=99
这里说明:第5行a和都先转换为int再进行相加,所以a+b这个过程值为65635,为int,如果它为short,那么会溢出为99,再通过赋值为int的话应该还是99,第6行,a+b为65635的int值,赋值为short,降级截断为99 (即65635%65536)。
2.涉及两种类型的运算,两个值会被转换为两种类型的更高级级别。
3.在赋值表达式中,计算的最终结果会被转换为被赋值变量的类型。这里会有升级和降级的发生。
注意:升级分为两种
- char --> int,比如8位的char’a‘,其阿斯克码为97,转为32位int,不用考虑内存里面涉及的操作,直接理解为8位的97,变成32位的97,而8到32之间的位是如何的不需要考虑,因为类型转换还没有到数据类型的位储存的深度,并不是直接将8位的97二进制码扩充或者复制粘贴到32位,如果是这样的话很容易会去想那么8到32之间怎么办,这里直接理解为用32位的97替换了8位的97;
- int -->float,这里不讨论float与double之间的转换,将他们视为一类,因为他们的储存方式相同,比如int a = 125,转换为flout类型,为125.000000,flout类型的精度为小数点后6位(十进制),同样的,这里类型转换不是简单的换一种方式去读取a的内存二进制储存内容,而是将整数值以浮点类型进行转换再储存到内存的二进制,比如125二进制为:
? 0000 0000 0000 0000 0000 0000 0111 1101
? 如果转换是直接用flout的储存规则来读取上面的125二进制码的话那么就不是125.000000,而是 0.000000,是一个无穷小的数,以前我会想到8位的char转为32位的int,那么如果是像刚才那样不是在类型层面的转换,而是直接换读取规则的话,原来是8位,现在用32位去读8位,这不是有点有点像越界访问了么,千万不要这样去单纯的理解类型转换,类型转换是在类型层面的转换,不是在储存层面的直接访问和读取写入这么简单,是将值先拿出来,再将它按转换的类型格式去储存,不是单纯的读取.
降级:
- int–> char,如int a =1107,char b = a ;这种降级,b的结果为1107%256,阿斯克码为83,char本质上就是int类型的一种子类型,因为char的储存方式和int一样,char字符与int之间联系是通过阿斯克码进行的,所以这里降级32位变为8位,直接是截断,只读取低八位,
- flout–>int,如int a = 125.987,那么a的结果为125,直接丢弃小数部分,不会四舍五入,精度丢失,也不涉及上面讲的储存层面的转换,而是单纯的类型转换后再储存,所以降级是非常可怕的,会有精度丢失的情况发生。还有注意这里的截断是趋零截断,3.2–>3,-3.2–>-3而不是-4。
4.函数传参的类型转换,这里涉及到很复杂储存内容这里现在不讨论。
|