杨玉磊 · 更新于 2018-07-23 04:00:43

类型转换

在 C 语言的表达式赋值时,要小心背后默默的隐式类型转换,它们会导致隐藏的 Bug。

C语言的整型提升规则

C的整型算数运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换为普通整型

例:
char a,b,c ;
a = b+c ;

注意,根据整型提升规则,上面b和c的值被提升为普通整型,然后再执行加法运算。加法运算的结果被截断再存储于a中。

在整数运算时,操作数是放到两个寄存器中进行的(32位计算机寄存器是32位 故字符型变量被提升为整型,计算的结果又被传回到内存中的字符型存储位置中故被截断)

【所以,最好把字符型定义为int型,尤其是涉及运算时】

例:
signed char a = 0xe0;
unsigned int b = a;
unsigned char c = a;

b的十六进制表示:
a 是一个 signed char,赋值给 unsigned int 的 b,并不是直接在前面若干个字节补 0。
而是,首先 signed char a 转换为 int(0xffffffe0),然后 int 转换成 unsigned int(0xffffffe0),所以最初是符号扩展,然后一个 int 赋值给了 unsigned int。

c的十六进制表示为0xe0,但 a == c 为假。
虽然 a 和 c 的二进制表示一模一样,都是 0xe0,但a == c中,a和c都要先转换成int型,再比较。a转int型为负数,b转int型为正数,故它俩不等。

对无符号类型的建议:

  • 尽量不要在你的代码中使用无符号类型,以免增加不必要的复杂性。
  • 尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况。
  • 只有在使用位段和二进制掩码时,才使用无符号数。

在涉及数值运算时,还要注意溢出的情况。

例:
int a=5000 ;
int b=25 ;
long c=a*b ;

表达式a*b以整型进行计算,若在16位的计算机上,这个乘法可能会产生溢出!
故应该显式转换: long c =(long)a*b ;
【在进行算术运算时一定要警惕乘法加法的可能溢出,尤其注意赋值号两边的数据类型保持一致

上一篇: 函数指针 下一篇: 输入