先上题目
#include <stdio.h> int main(void) { unsigned char a = 0xff; char b = 0xff; int c = a==b; // true, or false? printf("C: %d\n",c); }输出是什么?
其实不是1而是0!
解析:
如果int能够表示原始类型中的所有数值,那么这个数值就被转成int型,否则,它被转成unsigned int型。这种规则被称为整型提升。所有其它类型都不会被整型提升改变。
可以看出有符号或者无符号的char、short都可以被signed int表示,所以当它们作算术运算时,都会被转成signed int。
在前面的例子中, unsigned char a = 0xff
的值是255。但是, char b = 0xff
的值是-1。当它们都被转为int类型时,a
仍然是255,即 0x000000ff
, 而b
却变成0xffffffff
,代表整型中的-1。以下代码可以证明:
#include <stdio.h> int main(void) { unsigned char a = 0xff; char b = 0xff; printf("A: %08x, B: %08x\n", a, b); return 0; }
输出结果是:
转换:根据操作数的不同,某些运算符会引起操作数的值从某种类型转换为另一种类型。
1.整形提升
在一个表达式中,凡是可以使用整形的地方都可以使用带符号或无符号的字符、短整形或整形字段,还可以使用枚举类型的对象。如果原始类型的所有值都可以用int类型表示,则其值将转换为int类型;否则将被转换为unsigned int 类型。这一过程称为整形提升。
2.整形转换
将任何整数转换为某种指定的无符号类型数的方法是:以该符号类型能够表示的最大值加1为模,找出与此整数同余的最小非负值。在对二的补码表示中,如果该无符号类型的位模式较窄,这就相当于左截取;如果该无符号类型的位模式较宽,这就相当于对带符号值进行符号扩展和对无符号值进行0填充。
将任何整数转换为带符号类型时,如果它可以在新类型中表示出来,则其值保持不变,否则它的值同具体的实现有关。
对带符号值进行符号扩展 对无符号值进行0填充
3.整数和浮点数
当把浮点类型的值转化为整型时,小数部分将被丢弃。如果结果值不能用整型表示,则其行为是未定义的。特别是,将负的浮点数转换为无符号整型的结果是没有定义的。
当把整型值转换为浮点类型时,如果该值在浮点类型可表示的范围内但不能精确表示,则结果可能是下一个较高或较低的可表示值。如果该值超出可表示的范围,则其行为是未定义的。
4.浮点类型
将一个精度较低的浮点值转化为相同或更高精度的浮点类型时,它的值保持不变。将一个较高精度的浮点类型值转换为较低精度的浮点类型时,如果它的值在可表示范围内,则结果可能是下一个较高或较低的表示值。如果结果在可表示范围之外,则其行为是未定义的。
低精度--->高精度
高精度---->低精度
5.算术类型转换
许多运算符都会以类似的方式在运算过程中引起转换,并产生结果类型。其效果是将所有操作数转换为同一公共类型,并以此作为结果的类型。这种方式的转换称为普通算术类型转换。
首先,如果任何一个操作数为long double 类型,则将另一个操作数转换为long double 类型。
否则,如果任何一个操作数为double 类型,则将另一个操作数转换为double类型。
否则,如果任何一个操作数为float类型,则将另一个操作数转换为float类型。
否则,同时对两个操作数进行整形提升;然后,如果任何一个操作数为unsigned long int 类型,则将另一个操作数转化为unsigned long int 类型。
否则,如果一个操作数为long int类型且另一个操作数为unsigned int类型,则结果依赖于long int 类型是否可以表示所有的unsigned int 类型的值。如果可以,则将unsigned int 类型的操作数转换为long int ;如果不可以,则将两个操作数都转换为unsigned long int 类型。
否则,如果一个操作数为long int类型,则将另一个操作数转换为long int 类型。
否则,如果一个操作数为unsigned int 类型,则将另一个操作数转换为unsigned int 类型。
否则,将两个操作数都转换为Int 类型。
long double>double>float---进行整形提升--->unsigned long int>long int>unsigned int>int
注意:
第一,对于float类型操作数的算术运算可以只用单精度而不用双精度。
第二,当较短的无符号类型与较长的无符号类型一起运算时,不将无符号类型的属性传递给结果类型;
当一个无符号表达式与一个具有同样长度的带符号表达式相比较时,结果仍然是无法预测的。
(新规则虽然稍微复杂一些,但减少了无符号数与带符号数混合使用情况下的麻烦。from The C Programming Language Second Edition)
通常情况下,在对int类型的数值作运算时,CPU的运算速度是最快的。
在x86上,32位算术运算的速度比16位算术运算的速度快一倍。
C语言是一个注重效率的语言,所以它会作整型提升,使得程序的运行速度尽可能地快。
因此,你必须记住整型提升规则,以免发生一些整型溢出的问题。
转载注明出处