Поделиться через


Предупреждение компилятора (уровень 2) C4146

оператор unary минус, примененный к типу без знака, результат по-прежнему не назначен

Неподписанные типы могут содержать только неотрицательные значения, поэтому унарный минус (отрицание) обычно не имеет смысла при применении к неподписанному типу. Операнды и результат не являются отрицательными.

Замечания

При выражении отрицательного целочисленного литерала - перед значением анализируется как унарный оператор отрицания . Компилятор применяет оператор после анализа числового значения. Если числовое значение соответствует диапазону целого числа без знака, но не соответствующему типу целого числа со знаком, компилятор интерпретирует значение как незначимое. Неподписаемое значение не изменяется оператором унарного отрицания.

Это предупреждение часто возникает при попытке выразить минимальное int значение, -2147483648 или минимальное long long значение -9223372036854775808. Эти значения не могут быть записаны как -2147483648 или -922372036854775808ll соответственно. Причина заключается в том, что компилятор обрабатывает выражение двумя этапами: сначала он анализирует числовое значение, а затем применяет оператор отрицания. Например, если компилятор анализирует 2147483648, выполните следующие действия:

  1. Вычисляется число 2147483648. Так как это больше максимального int значения 2147483647, но по-прежнему соответствует unsigned intтипу 2147483648 unsigned int.

  2. Унарный минус применяется к значению без знака с результатом без знака, который также может быть 2147483648.

Неподписанный тип результата может вызвать непредвиденное поведение. Если результат используется в сравнении, то может использоваться сравнение без знака, например, если другой операнду является int.

Вы можете избежать использования C4146 или LLONG_MIN эквивалента <limits.h> INT_MIN C++<climits>. Эти значения имеют подписанные типы.

Параметр /sdl компилятора (включение дополнительных проверок безопасности) повышает этот предупреждение до ошибки.

Пример

В следующем примере показано непредвиденное поведение, которое может произойти при создании компилятором предупреждения C4146:

// C4146.cpp
// compile with: /W2
#include <iostream>

void check(int i)
{
    if (i > -9223372036854775808ll)   // C4146
        std::cout << i << " is greater than the most negative long long int.\n";
}

int main()
{
    check(-100);
    check(1);
}

В этом примере компилятор считает -9223372036854775808ll без знака, даже если литерал имеет ll суффикс и оператор отрицания применяется. Чтобы сделать сравнение, компилятор автоматически продвигает подписанный<.i unsigned long long int Ожидаемая вторая строка, не печатается, 1 is greater than the most negative long long intтак как ((unsigned long long int)1) > 9223372036854775808ull имеет значение false.

Чтобы исправить пример, включите <climits> и измените значение -9223372036854775808ll.LLONG_MIN

См. также

Унарный оператор отрицания (-)