安静的改变——隐式类型提升

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安静的改变——隐式类型提升相关的知识,希望对你有一定的参考价值。

C语言中有一些隐晦的地方也是容易造成bug的根源。

先说最常见的一种类型提升:

 1 #include<stdio.h>
 2 
 3 int main(void)
 4 {
 5     int m=-1;
 6     unsigned int n=1;
 7     m>n?printf("-1>1\\n"):printf("-1<=1\\n");
 8 
 9     return 0;
10 }

技术分享

在还是新手的时候,对于这样的现象很纳闷,也是自己写代码的时候很容易出bug的地方。这里的知识点是,当int和unsigned int比较时,int会被提升成无符号的,这样无符号的-1提升成一个很大的正整数,肯定大于1,那么运行结果也就不足为奇了。但是,既然知道了有这种提升存在,那么我们就应该知道c标准到底是怎么定义这样的提升的。

再看下面一个:

 1 #include<stdio.h>
 2 
 3 int main(void)
 4 {
 5     unsigned int a;
 6     int  b = -7;
 7     a=6;
 8     (a+b>6)?printf(">6\\n"):printf("<=6\\n");
 9     printf("%u\\n",a+b);
10     a=8;
11     (a+b>8)?printf(">8\\n"): printf("<=8\\n");/*执行加法之后,才进行类型提升*/
12     printf("%u\\n",a+b);
13     return 0;
14 }

技术分享

通过结果可以知道,在进行运算之后,才进行类型提升。当a=8,b=-7时,相加等于1,输出显式1<8,正确,这也证明了,-7在和8相加前,没有提升成无符号的,而是相加之后的数是无符号的,通过a=6,b=-7相加之后为-1,然后-1提升成无符号的,结果显示>6。

但是,这并没有结束,继续:

 1 #include<stdio.h>
 2 
 3 int main(void)
 4 {
 5     int a=-1;
 6     unsigned char b=1;
 7     a>b?printf(">\\n"):printf("<\\n");
 8     
 9     return 0;
10 }

技术分享

奇怪么,不是说好的无符号数和有符号数比较或者运算之后会提升成无符号的么,那这里怎么显示-1<1了啊?按道理-1转换成无符号的应该大于1啊。这个测试证明了一点,我们对ANSI C标准解释不完全。

类型提升,在ANSI C上举了很多例子,也有点晦涩,用自己的话总结就是:

在无符号和有符号的数运算中,数据类型朝着更大的类型转化,int和unsigned int,后者更大,故转化成后者,int和unsigned char,前者更大,故两者运算时,显示的类型为int,既然为int,自然可以比较-1和1的大小。但是这里地描述并不完全正确,因为还要考虑一个值溢出问题。

以上是关于安静的改变——隐式类型提升的主要内容,如果未能解决你的问题,请参考以下文章

隐式类型转换和整型提升

类型转换 隐式转换 自动提升 强制转换

C语言二操作符详解(隐式类型转换之整型提升,算术转换)

为啥 int 被提升为 double 而不是 float 以进行隐式转换

每天学一点系列~看得见摸不着的“隐式类型转换”

C语言隐式类型转换和算术转换详讲