简体   繁体   English

C++ 隐式转换(有符号 + 无符号)

[英]C++ Implicit Conversion (Signed + Unsigned)

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.我明白,关于隐式转换,如果我们有一个无符号类型操作数和一个有符号类型操作数,并且无符号操作数的类型与有符号操作数的类型相同(或大于),则有符号操作数将被转换未签名。

So:所以:

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如果无符号类型中的值不适合较大类型,则有符号操作数将转换为无符号类型

so in the following code:所以在下面的代码中:

signed long long s = -8;
unsigned int u = 10;
std::cout << s + u << std::endl;

u will be converted to signed long long because int values can fit in signed long long?? u将被转换为signed long long 因为int 值可以放入signed long long 中??

If that's the case, in what scenario the smaller type values won't fit in the larger one?如果是这种情况,在什么情况下较小的类型值不适合较大的类型值?

Relevant quote from the Standard:标准中的相关引述:

5 Expressions [expr] 5 表达式 [expr]

10 Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. 10 许多期望算术或枚举类型操作数的二元运算符会以类似的方式导致转换和产生结果类型。 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:这种模式称为通常的算术转换,其定义如下:

[2 clauses about equal types or types of equal sign omitted] [关于等号类型或等号类型省略的2个子句]

— 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. — 否则,两个操作数都应转换为与带符号整数类型的操作数类型对应的无符号整数类型。

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)让我们为上述 3 个子句中的每一个考虑以下 3 个示例案例,其中sizeof(int) < sizeof(long) == sizeof(long long) (很容易适应其他情况)

#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) << "\n"; // 4294967294
    std::cout << (s2 + u2) << "\n"; // -2 
    std::cout << (s3 + u3) << "\n"; // 18446744073709551614  
}

Live example with output.带有输出的实时示例

First clause: types of equal rank, so the signed int operand is converted to unsigned int .第一个子句:相等等级的类型,因此有signed int操作数转换为unsigned int This entails a value-transformation which (using two's complement) gives te printed value.这需要一个值转换(使用二进制补码)给出 te 打印值。

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第二条:有符号类型有更高的等级,并且(在这个平台上!)可以表示无符号类型的所有值,所以无符号操作数转换为有符号类型,你得到-2

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.第三个子句:signed 类型再次有更高的等级,但是(在这个平台上!)不能代表 unsigned 类型的所有值,所以两个操作数都被转换为unsigned long long ,并且在对有符号操作数进行值转换后,你得到印刷价值。

Note that when the unsigned operand would be large enough (eg 6 in these examples), then the end result would give 2 for all 3 examples because of unsigned integer overflow.请注意,当无符号操作数足够大(例如在这些示例中为 6)时,由于无符号整数溢出,所有 3 个示例的最终结果将为 2。

(Added) Note that you get even more unexpected results when you do comparisons on these types. (已添加)请注意,当您对这些类型进行比较时,您会得到更多意想不到的结果。 Lets consider the above example 1 with < :让我们考虑上面带有<示例 1:

#include <iostream>

signed int s1 = -4;
unsigned int u1 = 2;
int main()
{
    std::cout << (s1 < u1 ? "s1 < u1" : "s1 !< u1") << "\n";  // "s1 !< u1"
    std::cout << (-4 < 2u ? "-4 < 2u" : "-4 !< 2u") << "\n";  // "-4 !< 2u"
}

Since 2u is made unsigned explicitly by the u suffix the same rules apply.由于u后缀显式地使2u unsigned ,因此适用相同的规则。 And the result is probably not what you expect when comparing -4 < 2 when writing in C++ -4 < 2u ...结果可能不是您在用 C++ -4 < 2u编写时比较-4 < 2时所期望的......

signed int does not fit into unsigned long long . signed int不适合unsigned long long So you will have this conversion: signed int -> unsigned long long .所以你会有这个转换: signed int -> unsigned long long

Note that the C++11 standard doesn't talk about the larger or smaller types here, it talks about types with lower or higher rank.请注意,C++11 标准在这里不讨论较大或较小的类型,而是讨论具有较低或较高等级的类型。

Consider the case of long int and unsigned int where both are 32-bit.考虑long intunsigned int ,它们都是 32 位。 The long int has a larger rank than the unsigned int , but since long int and unsigned int are both 32-bit, long int can't represent all the values of unsigned int . long int的等级高于unsigned int ,但由于long intunsigned int都是 32 位,因此long int不能表示unsigned int所有值。

Therefore we fall into to the last case (C++11: 5.6p9):因此我们陷入了最后一种情况(C++11:5.6p9):

  • Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.否则,两个操作数都应转换为与带符号整数类型的操作数类型对应的无符号整数类型。

This means that both the long int and the unsigned int will be converted to unsigned long int .这意味着long intunsigned int都将转换为unsigned long int

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM