类型转换

Integer Promotion

在一个表达式中,凡是可以使用int或unsigned int类型做右值的地方也都可以使用有符号或无符号的char型、 short型和Bit-field。如果原始类型的取值范围都能用int型表示,则其值被提升为int型,如果表示不了就提升为unsigned int型,这称为Integer Promotion。做IntegerPromotion只影响上述几种类型的值,对其它类型无影响。

Integer Promotion适用于以下几种情况:

(1)如果一个函数的形参类型未知,或者函数的参数列表中有...,那么调用函数时要对相应的实参做Integer Promotion,此外,相应的实参如果是float型的也要被提升为double型,这条规则称为Default Argument Promotion。

例如:printf的参数列表中有...,除了第一个形参之外,其它形参的类型都是未知的,因此我们在调用printf("%c", 'A')时,'A'其实被提升为int型之后才传给了printf。

(2)算术运算中的类型转换。两个算术类型的操作数做算术运算,比如a * b,如果两边操作数的类型不同,编译器会自动做类型转换,使两边类型相同之后才做运算,这称为Usual Arithmetic Conversion,转换过程中有一步就是Integer Promotion。

例如:

unsigned char c1 = 255, c2 = 2;
int n = c1 + c2;

计算表达式c1 + c2的过程其实是先把c1和c2提升为int类型然后相加( unsigned char的取值范围是0~255,完全可以用int表示,所以不需要提升为unsigned int),整个表达式的值也是int型,最后的结果是257。假如没有这个提升的过程, c1 + c2就溢出了。 

Usual Arithmetic Conversion

1. 如果有一边的类型是long double,则把另一边也转成long double。

2. 否则,如果有一边的类型是double,则把另一边也转成double。

3. 否则,如果有一边的类型是float,则把另一边也转成float。

4. 否则,两边应该都是整数类型,做Integer Promotion,然后如果类型仍不相同,则需要继续转换。首先规定char、 short、 int、 long、 long long的转换级别( Integer Conversion Rank) 一个比一个高,同一类型的有符号和无符号数具有相同的Rank,然后有如下转换规则:

a. 如果两边都是有符号数,或者都是无符号数,那么较低Rank的类型转换成较高Rank的类型。例如unsigned int和unsigned long做算术运算时都转成unsigned long。

b. 否则,如果一边是无符号数另一边是有符号数,无符号数的Rank不低于有符号数的Rank,则把有符号数转成另一边的无符号类型。例如unsigned long和int做算术运算时都转成unsigned long, unsigned long和long做算术运算时也都转成unsignedlong。

c. 剩下的情况就是:一边是无符号数另一边是有符号数,并且无符号数的Rank低于有符号数的Rank。这时又分为两种情况,如果这个有符号数类型能够覆盖这个无符号数类型的取值范围,则把无符号数转成另一边的有符号类型。例如遵循LP64的平台上unsigned int和long在做算术运算时都转成long。

d. 否则,也就是这个符号数类型不足以覆盖这个无符号数类型的取值范围,则把两边都转成两者之中较高Rank的无符号类型。例如遵循ILP32的平台上unsigned int和long在做算术运算时都转成unsigned long。 

由赋值产生的类型转换 

如果赋值或初始化时等号两边的类型不相同,则编译器会把等号右边的类型转换成等号左边的类型再做赋值。例如int c = 3.14;,编译器会把右边的double型转成int型再赋给变量c。 

函数调用传参的过程相当于定义形参并且用实参对其做初始化,函数返回的过程相当于定义一个临时变量并且用return的表达式对其做初始化,所以由赋值产生的类型转换也适用于这两种情况。例如一个函数的原型是int foo(int, int);,则调用foo(3.1, 4.2)时会自动把两个double型的实参转成int型赋给形参,如果这个函数定义中有返回语句return 1.2;,则返回值1.2会自动转成int型再返回。 

强制类型转换

以上三种情况通称为隐式类型转换( Implicit Conversion,或者叫Coercion),编译器根据它自己的一套规则将一种类型自动转换为另一种类型。除此之外,程序员也可以通过类型转换运算符(Cast Operator)自己规定某个值要转换成何种类型,这称为显式类型转换(Explicit Conversion) 或强制类型转换(Type Cast)。

例如:计算表达式(double)3 + i,首先将整数3强制转换成double型3.0,然后和整型变量i相加,这时适用Usual Arithmetic Conversion规则,首先把i也转成double型,然后两者相加,最后整个表达式的值也是double型的。这里的(double)就是一个类型转换运算符,这种运算符由一个类型名加()括号组成,后面的3是这个运算符的操作数。

 

posted @ 2018-04-07 11:02  刘-皇叔  阅读(292)  评论(0)    收藏  举报