奇怪的类型推导

Afs*_*hin 6 c++ integer expression implicit-conversion

今天我看到了一个非常奇怪的类型推导。这是代码:

unsigned int y = 15;
int k = 5;
auto t = k - y / 2;
Run Code Online (Sandbox Code Playgroud)

由于kis int,我认为该类型也t应该是int。但令我惊讶的是,它的类型是unsigned int. 我找不到为什么类型被推断为unsigned int. 知道为什么吗?

Vla*_*cow 6

由于通常的算术转换,如果两个操作数具有相同的转换等级并且其中一个操作数具有无符号整数类型,则表达式的类型具有相同的无符号整数类型。

来自 C++ 17 标准(5 个表达式,第 10 页)

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

注意类型的转换等级unsigned int等于类型int( signed int)的等级。来自 C++ 17 标准(4.13 整数转换等级,p.#1)

— 任何无符号整数类型的等级应等于相应有符号整数类型的等级

下面是一个更有趣的例子。假设有两个声明

unsigned int x = 0;
long y = 0;
Run Code Online (Sandbox Code Playgroud)

并且这两种类型的宽度相同并且等于例如4字节。众所周知,类型long的等级大于类型的等级unsigned int。一个问题出现了什么id表达式的类型

x + y
Run Code Online (Sandbox Code Playgroud)

表达式的类型是unsigned long.:)

这是一个演示程序,但不是类型longunsigned int而是使用类型long longunsigned long

#include <iostream>
#include <iomanip>
#include <type_traits>

int main() 
{
    unsigned long int x = 0;
    long long int y = 0;

    std::cout << "sizeof( unsigned long ) = " 
              << sizeof( unsigned long )
              << '\n';

    std::cout << "sizeof( long long ) = " 
              << sizeof( long long )
              << '\n';

    std::cout << std::boolalpha 
              << std::is_same<unsigned long long, decltype( x + y )>::value
              << '\n';

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序输出是

sizeof( unsigned long ) = 8
sizeof( long long ) = 8
true
Run Code Online (Sandbox Code Playgroud)

即表达式的类型x + yunsigned long long虽然既不操作数的表达式的具有此类型。

  • @Afshin 来自 C++ 17 标准的引用,但同样适用于所有 C++ 标准和 C 标准。 (2认同)