为什么固定宽度无符号整数的输出为负而无符号整数输出按预期回绕?

Why is the output of fixed width unsigned integer negative while unsigned integer output wraps around as expected?

#include <iostream>

#define TRY_INT

void testRun() 
{
    #ifdef TRY_INT          //test with unsigned
    unsigned int value1{1}; //define some unsigned variables
    unsigned int value2{1};
    unsigned int value3{2};
    #else                   //test with fixed width
    uint16_t value1{1};     //define fixed width unsigned variables
    uint16_t value2{1};
    uint16_t value3{2};

    #endif

    if ( value1 > value2 - value3 )
    {
        std::cout << value1 << " is bigger than: " << value2 - value3 << "\n";
    }
    else
    {
        std::cout << value1 << " is smaller than: " << value2 - value3 << "\n";
    }

}

int main()
{
    testRun();

    return 0;
}

使用无符号整数我得到:

1 is smaller than: 4294967295

使用固定宽度的 unsigned int,输出为:

1 is smaller than: -1

我的预期是它也会环绕,这与 std::cout 有关系吗?

估计是积分提升造成的。引用形式 cppreference:

...arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion, if applicable.

unsigned char, char8_t (since C++20) or unsigned short can be converted to int if it can hold its entire value range...

因此,如果 uint16_t 在您的实现中只是 unsigned short 的别名,则 value2 - value3 是使用 int 类型计算的,结果也是 int,这就是显示 -1 的原因。

对于 unsigned int,不应用任何提升,整个计算都以此类型执行。


在最新的在线C++ Draft中,参见[conv.prom/1]:

A prvalue of an integer type other than bool, char16_­t, char32_­t, or wchar_­t whose integer conversion rank is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

unsigned int等同于uint32_tunsigned short int等同于uint16_t.

因此,如果您使用 unsigned short int 而不是 unsigned int,您将获得与 uint16_t.

相同的行为

为什么会得到-1?

如果 int 可以容纳 unsigned short int 的所有可能值,则积分提升将尝试将 unsigned short int 转换为 int。另一方面,如果不是这种情况,将执行到 unsigned int 的积分提升。

因此减法最有可能在 int 类型中完成,而不是 uint16_t.