C++ 隐式转换(有符号 + 无符号)
我了解,关于隐式转换,如果我们有一个无符号类型操作数和一个有符号类型操作数,并且无符号操作数的类型与有符号操作数的类型相同(或大于),则有符号操作数将被转换为无符号.
I understand that, regarding implicit conversions, if we have an unsigned type operand and a signed type operand, and the type of the unsigned operand is the same as (or larger) than the type of the signed operand, the signed operand will be converted to unsigned.
所以:
unsigned int u = 10;
signed int s = -8;
std::cout << s + u << std::endl;
//prints 2 because it will convert `s` to `unsigned int`, now `s` has the value
//4294967288, then it will add `u` to it, which is an out-of-range value, so,
//in my machine, `4294967298 % 4294967296 = 2`
我不明白 - 我读到如果有符号操作数的类型大于无符号操作数:
What I don't understand - I read that if the signed operand has a larger type than the unsigned operand:
如果无符号类型中的所有值都适合较大的类型,则无符号操作数将转换为有符号类型
if all values in the unsigned type fit in the larger type then the unsigned operand is converted to the signed type
如果无符号类型中的值不适合更大的类型,则有符号操作数将转换为无符号类型
if the values in the unsigned type don't fit in the larger type, then the signed operand will be converted to the unsigned type
所以在下面的代码中:
signed long long s = -8;
unsigned int u = 10;
std::cout << s + u << std::endl;
u
将被转换为signed long long,因为int 值可以适合signed long long??
u
will be converted to signed long long because int values can fit in signed long long??
如果是这样,在什么情况下较小的类型值不适合较大的类型值?
If that's the case, in what scenario the smaller type values won't fit in the larger one?
推荐答案
标准相关引用:
5 个表达式 [expr]
10 许多二元运算符需要算术或运算操作数枚举类型导致转换并产生类似的结果类型大大地.目的是产生一个通用类型,这也是结果.这种模式称为通常的算术转换,定义如下:
10 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 de?ned as follows:
[关于等号类型或等号类型省略的2条子句]
[2 clauses about equal types or types of equal sign omitted]
― 否则,如果具有无符号整数类型的操作数具有秩大于或等于另一个操作数的类型的等级,带符号整数类型的操作数应转换为无符号整数类型的操作数.
― Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
――否则,如果类型带符号整数类型的操作数可以表示所有值无符号整数类型的操作数的类型,操作数具有无符号整数类型的应转换为带符号整数类型的操作数.
― Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
――否则,两个操作数都应为转换为类型对应的无符号整数类型带符号整数类型的操作数.
― Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
让我们在 sizeof(int) <sizeof(long) == sizeof(long long)
(容易适应其他情况)
Let's consider the following 3 example cases for each of the 3 above clauses on a system where sizeof(int) < sizeof(long) == sizeof(long long)
(easily adaptable to other cases)
#include <iostream>
signed int s1 = -4;
unsigned int u1 = 2;
signed long int s2 = -4;
unsigned int u2 = 2;
signed long long int s3 = -4;
unsigned long int u3 = 2;
int main()
{
std::cout << (s1 + u1) << "
"; // 4294967294
std::cout << (s2 + u2) << "
"; // -2
std::cout << (s3 + u3) << "
"; // 18446744073709551614
}
Live 示例与输出.
Live example with output.
第一个子句:等级相等的类型,因此 signed int
操作数被转换为 unsigned int
.这需要一个值转换,它(使用二进制补码)给出打印值.
First clause: types of equal rank, so the signed int
operand is converted to unsigned int
. This entails a value-transformation which (using two's complement) gives te printed value.
第二个子句:有符号类型具有更高的等级,并且(在这个平台上!)可以表示无符号类型的所有值,因此将无符号操作数转换为有符号类型,你得到-2
Second clause: signed type has higher rank, and (on this platform!) can represent all values of the unsigned type, so unsigned operand is converted to signed type, and you get -2
第三条:有符号类型再次具有更高的等级,但是(在这个平台上!)不能代表无符号类型的所有值,所以两个操作数都转换为unsigned long long
,并且在值之后- 对有符号操作数进行转换,得到打印值.
Third clause: signed type again has higher rank, but (on this platform!) cannot represent all values of the unsigned type, so both operands are converted to unsigned long long
, and after the value-transformation on the signed operand, you get the printed value.
请注意,当无符号操作数足够大(例如这些示例中的 6 个)时,由于无符号整数溢出,最终结果将为所有 3 个示例给出 2.
Note that when the unsigned operand would be large enough (e.g. 6 in these examples), then the end result would give 2 for all 3 examples because of unsigned integer overflow.
(已添加)请注意,当您对这些类型进行比较时,您会得到更多意想不到的结果.让我们用 <
来考虑上面的示例 1:
(Added) Note that you get even more unexpected results when you do comparisons on these types. Lets consider the above example 1 with <
:
#include <iostream>
signed int s1 = -4;
unsigned int u1 = 2;
int main()
{
std::cout << (s1 < u1 ? "s1 < u1" : "s1 !< u1") << "
"; // "s1 !< u1"
std::cout << (-4 < 2u ? "-4 < 2u" : "-4 !< 2u") << "
"; // "-4 !< 2u"
}
由于 2u
是由 u
后缀显式地制成 unsigned
的,因此适用相同的规则.当比较 -4 < 时,结果可能不是您所期望的.2 用 C++ 编写时 -4 <2u
...
Since 2u
is made unsigned
explicitly by the u
suffix the same rules apply. And the result is probably not what you expect when comparing -4 < 2 when writing in C++ -4 < 2u
...
相关文章