This is outlined explicitly in §5/9:
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
- If either operand is of type
long double
, the other shall be converted to long double
.
- Otherwise, if either operand is
double
, the other shall be converted to double
.
- Otherwise, if either operand is
float
, the other shall be converted to float
.
- Otherwise, the integral promotions shall be performed on both operands.
- Then, if either operand is
unsigned long
the other shall be converted to unsigned long
.
- Otherwise, if one operand is a
long int
and the other unsigned int
, then if a long int
can represent all the values of an unsigned int
, the unsigned int
shall be converted to a long int
; otherwise both operands shall be converted to unsigned long int
.
- Otherwise, if either operand is
long
, the other shall be converted to long
.
- Otherwise, if either operand is
unsigned
, the other shall be converted to unsigned
.
[Note: otherwise, the only remaining case is that both operands are int
]
In both of your scenarios, the result of operator+
is unsigned
. Consequently, the second scenario is effectively:
int result = static_cast<int>(us + static_cast<unsigned>(neg));
Because in this case the value of us + neg
is not representable by int
, the value of result
is implementation-defined – §4.7/3:
If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…