C语言 算术转换 unsigned signed int

来源:互联网 发布:学党史知国史征文300字 编辑:程序博客网 时间:2024/05/29 05:05

在C语言中,如果运算符的两个操作符不相同,那么它们之间对进行一定的算术转化,然后再进行运算操作。说明这个规则之前,先看一个例子

int x = -1;int y = 5;unsigned int z = 5;if(x < y)printf("true ");elseprintf("false ");if(x < z)printf("true ");elseprintf("false ");


大多数初次接触这个问题的人可能觉得输出结果应该是true true,实际上在编译器中的结果应该是true faluse

第一个true没有任何问题,而第二个却让人疑惑,-1<5是公认的,那为何unsigned 5的却变成false了呢?

事实上-1仍然是-1,5仍然是5,只是编译器默认的算术转化规则导致的。

根据现象推本质,我们猜测是因为-1被转化成了unsigned int ,也就是一个非常大的正数,所以它比5要大。实际就是这样,当int和unsigned比较的时候,int会被转化为unsigned型

再看下面这个:

if(x < (unsigned int)5)printf("-1 is less than int 5");if(x < (unsigned short)5)printf("-1 is less than short 5");


有了上面的例子做参考,我们可以知道"-1 is less than int 5"是不会打印的,后一句呢?

运行结果是"-1 is less than short 5",后面一句被打印出来了。这里有一个很有趣的情况,(unsigned int)5和(unsigned short)5 无疑是相等的,但和-1相比较它们又“不等了”

由上面两个例子可以一窥“算术转化”的规则,基于记忆,我们一般认为“数据类型一般朝着浮点精度更高,长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned”

ANSI C(区别于K&R C)中,转换规则是这样的

如果一个数是long double,那么另一个数也被转换为long double,其次是double,再次是float;(语句意思同前一句,这里简化说明)

否则进行整型升级:同上面一样,首先如果一个数是unsigned long int,那么另一个数也被转换为unsigned long int

其次,对于long int unsigned int, 将后者转化为long int(int 是16位),或将两者都转化为unsigned long int(int 是32位),即一种类型能不能完全表示另一种类型

再次,有long int 则转化为该类型

再再次,有unsigned int 则转化为该类型

如果都不属于,则都做int处理,即将short char都提升为int

 

依照这个规则,上述运行结果就可以解释了,主要问题是unsigned int 与int型的比较,结果可能超出预期,一般情况下,编译器是会给出警告信息的:

warning C4018: “<”: 有符号/无符号不匹配

 

----后话

也许有人会说,深究这个根本没有必要,程序中用强制类型转换就没有问题的。的确是这样,养成好的编程习惯,许多问题都能解决

要注意的是,常用的sizeof返回的就是unsigned int 型,如果将它的返回值与0比较没有问题,但是如果想当然地认为把0换成-1也一样的话,就很危险了。这也许不能算作是程序编写的bug,应该是C默认转换规则的bug

原创粉丝点击