繁体   English   中英

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

[英]C++ Implicit Conversion (Signed + 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`

我不明白的是 - 我读到如果有符号操作数的类型大于无符号操作数:

  • 如果无符号类型中的所有值都适合较大类型,则无符号操作数将转换为有符号类型

  • 如果无符号类型中的值不适合较大类型,则有符号操作数将转换为无符号类型

所以在下面的代码中:

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

u将被转换为signed long long 因为int 值可以放入signed long long 中??

如果是这种情况,在什么情况下较小的类型值不适合较大的类型值?

标准中的相关引述:

5 表达式 [expr]

10 许多期望算术或枚举类型操作数的二元运算符会以类似的方式导致转换和产生结果类型。 目的是产生一个通用类型,它也是结果的类型。 这种模式称为通常的算术转换,其定义如下:

[关于等号类型或等号类型省略的2个子句]

— 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则将具有符号整数类型的操作数转换为具有无符号整数类型的操作数的类型。

— 否则,如果有符号整数类型操作数的类型可以表示无符号整数类型操作数类型的所有值,则将无符号整数类型操作数转换为有符号整数类型操作数的类型。

— 否则,两个操作数都应转换为与带符号整数类型的操作数类型对应的无符号整数类型。

让我们为上述 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  
}

带有输出的实时示例

第一个子句:相等等级的类型,因此有signed int操作数转换为unsigned int 这需要一个值转换(使用二进制补码)给出 te 打印值。

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

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

请注意,当无符号操作数足够大(例如在这些示例中为 6)时,由于无符号整数溢出,所有 3 个示例的最终结果将为 2。

(已添加)请注意,当您对这些类型进行比较时,您会得到更多意想不到的结果。 让我们考虑上面带有<示例 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"
}

由于u后缀显式地使2u unsigned ,因此适用相同的规则。 结果可能不是您在用 C++ -4 < 2u编写时比较-4 < 2时所期望的......

signed int不适合unsigned long long 所以你会有这个转换: signed int -> unsigned long long

请注意,C++11 标准在这里不讨论较大或较小的类型,而是讨论具有较低或较高等级的类型。

考虑long intunsigned int ,它们都是 32 位。 long int的等级高于unsigned int ,但由于long intunsigned int都是 32 位,因此long int不能表示unsigned int所有值。

因此我们陷入了最后一种情况(C++11:5.6p9):

  • 否则,两个操作数都应转换为与带符号整数类型的操作数类型对应的无符号整数类型。

这意味着long intunsigned int都将转换为unsigned long int

暂无
暂无

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

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