C++的类型转换

《C++ Primer Plus》笔记

C++自动执行很多类型转换:

  • 将一种算术类型的值赋给另一种算术类型的变量时,C++将对值进行转换;
  • 表达式中包含不同的类型时,C++将对值进行转换;
  • 将参数传递给函数,C++将对值进行转换;

初始化和赋值进行的转换:

C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换为接收变量的类型。将一个值赋给取值范围更大的类型通常不会导致什么问题,只是占用的字节更多而已。然而,将一个很大的long值赋给float变量将降低精度。因为float只有6位有效数字。

潜在的数值转换问题:

转换 潜在的问题
将较大的浮点类型转换为较小的浮点类型,如将double转换为float 精度(有效数位)降低,值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的
将浮点类型转换为整型 小数部分丢失,原来的值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的
将较大的整型转换为 小数部分丢失,原来的值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的
较大的整型转换为较小的整型,如将long转换short 原来的值可能超出目标类型取值范围,通常只复制右边的字节

将0赋给bool变量时,将被转换为false;而非零值将被转换为true。

将浮点值赋给整型将导致两个问题。首先,将浮点值转换为整型会将数字截短(除掉小数部分)。其次,float值对于int变量来说可能太大了。在这种情况下,C++并没有定义结果应该是什么,这意味着不同的实现的反应可能不同。

当将整数变量初始化为浮点值时,有些编译器将提出警告,指出这可能丢掉数据(丧失精度)。

以{}方式初始化时进行的转换(C++11)

C++11将使用大括号的初始化成为列表初始化(list-initialization),因为这种初始化常用于给复杂的数据类型提供值列表,所以它对类型转换的要求更严格。具体地说,列表初始化不允许缩窄(narrowing),即变量的类型可能无法表示赋给它的值。例如,不允许将浮点型转换为整型(整型的表示范围没有浮点型表示的范围大)。在不同的整型之间转换或将整型转换为浮点型可能被允许,条件是编译器知道目标变量能够正确地存储赋给它的值。例如,可将long变量初始化为int值,因为long总是至少与int一样长;相反方向的转换也可能被允许,只要int变量能够存储赋给它的long常量;

表达式中的转换

当同一个表达式中包含两种不同的算术类型时,C++将执行两种自动转换:首先,一些类型在出现时便会自动转换;其次,有些类型在与其他类型同时出现在表达式中时将被转换。

自动转换:在计算表达式时,C++将bool、char、unsigned char、signed char和short值转换为int。例如true被转换为1,false被转换为0。这些转换被称为整型提升

short chickens = 20;
short ducks = 35;
short fowl = chickens + ducks;

在第三条语句中,C++程序先取得chickens和ducks的值,并将它们转换为int。然后,程序将结果转换为short类型,因为结果将被赋给一个short变量。

如果short比int短,则unsigned short类型将被转换为int;如果两种类型的长度相同,则unsigned short类型将被转换为unsigned int。此规则确保了在对unsigned short进行提升时不会损失数据。

wchar_t将被提升为下列类型中第一个宽度足够存储wchar_t取值范围的类型:int、unsigned int、long、unsigned long;

其它转换:将不同类型进行算术运算时,也会进行一些转换,例如将int和float相加时。当运算涉及两种类型时,较小的类型将被转换为较大的类型。例如将int和float相加时。当涉及两种类型时,较小的类型将被转换为较大的类型。编译器通过校验表来确定在算术表达式中执行的转换。C++11的校验表,编译器将依次查阅该列表。

  • 如果有一个操作数的类型是long double,则将另一个操作数转换为long double
  • 否则,如果有一个操作数的类型是double,则将另一个操作数转换为double
  • 否则,如果由一个操作数的类型是float,则将另一个操作数转换为float
  • 否则,说明操作数都是整型,因此执行整型提升即可。
  • 在这种情况下,如果两个操作数都是有符号或无符号的,且其中一个操作数的级别比另一个低,则转化为级别高的类型。
  • 如果一个操作数为有符号的,另一个操作数为无符号的,且无符号操作数的级别比有符号操作数高,则将有符号操作数转换为无符号操作数所属的类型。
  • 否则,如果有符号类型可以表示无符号类型的所有取值,则将无符号操作数转换为有符号操作数所属的类型;
  • 否则,将两个操作数都转换为有符号类型的无符号版本。

传递参数时的转换

传递参数时的类型转换通常由C++函数原型控制。然而,也可以取消原型对参数传递的控制,尽管这样做并不明智。在这种情况下,C++将对char和short类型(signed和unsigned)应用整型提升。另外,为保持与传统C语言中大量代码的兼容性,在将参数传递给取消原型对参数传递控制的函数时,C++将float参数提升为double参数。

强制类型转换

C++还允许通过强制类型转换机制显式地进行类型转换。强制类型转换的格式有两种。例如,为将存储在变量thorn中的int值转换为long类型,可以使用下述表达式中的一种:

(long) thorn;
long (thorn);

强制类型转换不会修改thorn变量本身,而是创建一个新的、指定类型的值,可以在表达式中使用这个值。

C++还引入了4个强制类型转换运算符,对它们的使用要求更为严格。

你可能感兴趣的:(C++)