Почему результат сравнения не такой, как ожидалось?

#c #if-statement #comparison #unsigned-integer

Вопрос:

Не могли бы вы объяснить, почему следующий код дает такие результаты?

 #include <iostream>
int main()
{
    int x = -1;
    unsigned int y = 1;
    if (x > y)
        std::cout << "true";
    else
        std::cout << "false";
}
 

Вывод = true но почему ?

Комментарии:

1. пожалуйста, по одному вопросу на вопрос. Они связаны, но все же 2 отдельных вопроса

2. Читайте о неявных преобразованиях

3. x > y становится static_cast<unsigned int>(x) > y .

4. @TedLyngmo Спасибо, я прочитаю об этой теме

5. Вот почему в C 20 появились утилиты для смешанных сравнений en.cppreference.com/w/cpp/utility/intcmp

Ответ №1:

Здесь происходит неявное преобразование из int в unsigned int , которое происходит следующим образом.

 int x = -a;
unsigned int y = x; //As far as y can hold only positive values, 
//it now holds UINT_MAX - (a   1)
 

Где UINT_MAX находится макрос, который определен как максимальное значение unsigned int , которое может содержаться.

В вашем случае x преобразуется в UINT_MAX , что, очевидно, больше 1

Ответ №2:

Что здесь происходит, так это то, что этот код:

     int x = -1;
    unsigned int y = 1;

    bool result = x > y;
 

преобразуется в:

     int x = -1;
    unsigned int y = 1;

    bool result = operator>(x, y);
 

Определены две функции operator> :

 bool operator>(int, int);
bool operator>(unsigned int, unsigned int);
 

Но ты звонишь operator>(int, unsigned int) . Таким образом, компилятор преобразовал ваш int со знаком в int без знака, а затем вызвал operator>(unsigned int, unsigned int) , что привело к ошибке.

Стандартный способ избежать этого-включить предупреждения компилятора. Вы можете использовать предупреждение-Wconversion, которое предупредит вас об этой конкретной проблеме, или, что еще лучше, пройти через стену, чтобы включить все предупреждения.

Чтобы исправить ошибку в коде, вы можете явно указать компилятору, как преобразовать аргументы в оператор сравнения

 #include <iostream>
int main()
{
    int x = -1;
    unsigned int y = 1;
    if (x > static_cast<int>(y))
        std::cout << "true";
    else
        std::cout << "false";
}
 

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