The language defines a set of conversions among the built-in types. Among these, the most common are the arithmetic conversions, which ensure that the two operands of a binary operator, such as an arithmetic or logical operator, are converted to a common type before the operator is eva luated. That common type is also the result type of the expression.
The rules define a hierarchy of type conversions in which operands are converted to the widest type in the expression. The conversion rules are defined so as to preserve the precision of the values involved in a multitype expression. For example, if one operand is of type long double, then the other is converted to type long double regardless of what the second type is.
The simplest kinds of conversion are integral promotions. Each of the integral types that are smaller than int—char, signed char, unsigned char, short, and unsigned short—is promoted to int if all possible values of that type fit in an int. Otherwise, the value is promoted to unsigned int. When bool values are promoted to int, a false value promotes to zero and true to one.
即使是这种最简单的整型提升也可能造成bug。例如,在大多数实现中char是有符号的,它的表示范围是 128~127,如果我们想把它转换成一个非负数,用于数组下标,那么static_cast<unsigned int>(aChar) 并不能达到效果。对于负值,转换的结果将会是一个非常大的整数,因为char 会被先提升为int, 再转换为unsigned int。正确的做法是static_cast<unsignedchar>(aChar),这样转换后的取值范围是0~255。
Conversions between Signed and Unsigned Types
When an unsigned value is involved in an expression, the conversion rules are defined to preserve the value of the operands. Conversions involving unsigned operands depend on the relative sizes of the integral types on the machine. Hence, such conversions are inherently machine dependent.
In expressions involving shorts and ints, values of type short are converted to int. Expressions involving unsigned short are converted to int if the int type is large enough to represent all the values of an unsigned short. Otherwise, both operands are converted to unsigned int. For example, if shorts are a half word and ints a word, then any unsigned value will fit inside an int. On such a machine, unsigned shorts are converted to int.
建议读者写代码验证这段话的内容,比如short sv= 30000; int iv = s*s;,看看iv 的值是多少。
The same conversion happens among operands of type long and unsigned int. The unsigned int operand is converted to long if type long on the machine is large enough to represent all the values of the unsigned int. Otherwise, both operands are converted to unsigned long.
On a 32-bit machine, long and int are typically represented in a word. On such machines, expressions involving unsigned ints and longs are converted to unsigned long.
Conversions for expressions involving signed and unsigned int can be surprising. In these expressions the signed value is converted to unsigned. For example, if we compare a plain int and an unsigned int, the int is first converted to unsigned. If the int happens to hold a negative value, the result will be converted as described in Section 2.1.1 (p. 36), with all the attendant problems discussed there.
无符号整数也是隐式类型转换bug 的常客,比方说(0U > -1)这个表达式的值竟然是false。有的语言干脆取消无符号整数,从而避免将一个负数强行转换为正数的尴尬。
Understanding the Arithmetic Conversions
The bestway to understand the arithmetic conversions is to study lots of examples. In most of the following examples, either the operands are converted to the largest type involved in the expression or, in the case of assignment expressions, the righthand operand is converted to the type of the left-hand operand:
- bool flag; char cval;
- short sval; unsigned short usval;
In the first addition, the character constant lowercase ’a’ has type char, which as we know from Section 2.1.1 (p. 34) is a numeric value. The numeric value that ’a’ represents depends on the machine’s character set. On our ASCII machine, ’a’
represents the number 97. When we add ’a’ to a long double, the char value is promoted to int and then that int value is converted to a long double. That converted value is added to the long double literal. The other interesting cases are the last two expressions involving unsigned values.