首页 > 代码库 > 安静的改变——隐式类型提升

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

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的大小。但是这里地描述并不完全正确,因为还要考虑一个值溢出问题。

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