C语言是一个强类型的语言,变量必须先定义再使用,而且变量如果不经过转换,那么将永远保持原来的类型。但强和弱是相对的,如果我们把C语言和其它的一些强类型语言相比较,我们会发现C语言的一些弱类型特性,这些特性会在某些时候坑害我们。当然,讨论强类型还是弱类型是没有意义的事情,重要的是从这些对比中学到一些东西,避免因此而犯下错误。

隐式类型转换——梦开始的地方

众所周知,对两个类型不同类型的数据操作时,如果这两个数据在一定的兼容范围内,C语言会对其中一个数据进行隐式的类型转换,优先级如下。

我们拿经典的JAVA语言举例,JAVA禁止了boolean整型数据之间的类型转换,也禁止了整型浮点型数据的转换,为语言提供了更高的安全性。如此丰富的类型转换,反映了C语言的"弱类型"特性,一方面是C语言为我们的编程提供了更高的自由度,另一方面也增大了隐患。

来看一个简单的例子。

1
2
3
4
5
6
7
int a = -1;
unsigned int b = 1;
if(a > b) {
printf("a > b");
} else {
printf("a < b");
}

输出的结果是

1
a > b

一个非常浅显易懂的例子,通过上面隐式类型转换的优先级我们知道有符号整数被转换成了无符号整数,而在有符号整数中最高位用1来代表负数,导致的结果就是转换后的a相当的大,造成了意料之外的错误。

对于C语言的初学者而言,对于无符号整数的应用频率比较低,所以一般情况下也不会造成这样的错误。但是下面的例子就不一定了。

小心库函数的返回值

处理字符串的标准库为我们提供了很多的方法,不知道你是否真正关注过它们的返回值类型,我们来看一个因为类型转换造成的错误。

1
2
3
4
5
if(-1 > strlen("A")){
printf("YES");
}else{
printf("NO");
}

输出

1
YES

从我们上面的错误中我们不难猜出strlen函数返回值是无符号整数类型,我们再来细看strlen,发现返回值类型是size_t,这是一个无符号整数类型,具体大小与平台有关。

总而言之,我们要小心隐式转换给我们带来的错误。