Почему вывод целого числа без знака с фиксированной шириной отрицателен, а вывод целого числа без знака переворачивается как ожидалось? - PullRequest
2 голосов
/ 06 апреля 2020
#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?

Ответы [ 2 ]

3 голосов
/ 06 апреля 2020

Я думаю, это вызвано интегральным продвижением . Форма цитирования cppreference :

... arithmeti c операторы не принимают типы, меньшие int, в качестве аргументов , и интегральные продвижения автоматически применяется после преобразования lvalue в rvalue, если применимо.

unsigned char, char8_t (начиная с C ++ 20) или unsigned short может быть преобразовано в int, если оно может содержать весь его диапазон значений ...

Следовательно, если uint16_t является просто псевдонимом для unsigned short в вашей реализации, value2 - value3 вычисляется с типом int и результатом также int, поэтому отображается -1.

При unsigned int повышение не применяется, и весь расчет выполняется в этом типе.


В последний онлайн черновик C ++, см. [conv.prom / 1] :

Значение целого типа, отличное от bool, char16_­t, char32_­t или wchar_­t, чей ранг целочисленного преобразования меньше, чем ранг int, может быть преобразован в значение типа int, если int может представлять все значения тип источника; в противном случае исходное значение может быть преобразовано в значение типа unsigned int.

2 голосов
/ 06 апреля 2020

unsigned int эквивалентно uint32_t и unsigned short int эквивалентно uint16_t.

Следовательно, если вы используете unsigned short int вместо unsigned int, вы получите то же поведение, что и для uint16_t.

Почему вы получаете -1?

Интегральное продвижение попытается преобразовать unsigned short int в int, если int может вместить все возможные значения unsigned short int. С другой стороны, если это не так, будет выполнено интегральное повышение до unsigned int.

Поэтому вычитание, скорее всего, выполняется в виде int, а не uint16_t.

...