Выражение «я & lt; 0 ‘всегда ложно

Для следующего фрагмента:

size_t i = 0;
std::wstring s;
s = (i < 0)   ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";

Анализ журналов анализа PVS-Studio для первого условия i < 0, как и ожидалось:

V547 Expression 'i < 0' is always false. Unsigned type value is never < 0. test_cpp_vs2017.cpp 19

Почему PVS не выдает никаких предупреждений о втором, также подозрительном состоянии i != -1 например, сообщать об этом как о правде?

25

Решение

Потому что это было бы бесполезным, недействительным предупреждением. size_t тип без знака, и из-за того, как работают целочисленные преобразования (см. [conv.integral] / 2), -1 преобразуется (неявно здесь) в size_t равно SIZE_MAX,

Рассмотрим тот факт, что это фактическое определение std::string::npos в libstdc ++:

static const size_type  npos = static_cast<size_type>(-1);

Если PVS-Studio предупредил о i != -1Будет ли это также необходимо предупредить о i != std::string::npos?

С другой стороны, значение без знака не может быть меньше 0, поскольку оно не имеет знака, поэтому i < 0 скорее всего, не то, что хотел программист, и поэтому предупреждение оправдано.

36

Другие решения

Это связано с неявные интегральные преобразования в обоих случаях. size_t должен быть беззнаковым типом, по крайней мере, 16 бит, и в вашем случае он имеет достаточный размер, ср. int что если один аргумент size_t а другой intтогда int аргумент преобразуется в size_t,

При оценке i < 0, 0 превращается в size_t тип. Оба операнда size_t так что выражение всегда false,

При оценке i != -1, -1 преобразуется в size_t тоже. Это значение будет std::numeric_limits<size_t>::max(),

Ссылка: http://en.cppreference.com/w/cpp/language/implicit_conversion

22

Когда значение преобразуется в без знака, если это значение не может быть представлено типом без знака, то значение будет преобразовано в значение (или, скорее, ценность) что является представимо и совпадает с исходным значением по модулю количества представляемых значений (что является максимальным представимым значением + 1 == 2N где n — количество бит)

Поэтому не о чем предупреждать, потому что есть какое-то значение, для которого условие может быть ложным (до тех пор, пока мы анализируем это выражение изолированно). i всегда равно 0, поэтому условие всегда выполняется, но чтобы доказать это, мы должны принять во внимание все выполнение программы).

-1 соответствует m — 1 по модулю m, поэтому -1 всегда преобразуется в максимальное представимое значение.

7

Были правильные важные ответы, но я хотел бы сделать некоторые разъяснения. К сожалению, тестовый пример сформирован неправильно. Мы можем написать так:

void F1()
{
size_t i = 0;
std::wstring s;
s = (i < 0)   ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
}

В таком случае анализатор выдаст два V547 предупреждения:

  • V547 Expression ‘I < 0 ‘всегда ложно. Значение типа без знака никогда не бывает
    < 0. consoleapplication1.cpp 15
  • V547 Выражение «i! = — 1» всегда
    правда. consoleapplication1.cpp 16

(V519 тоже будет проходить, но это не относится к вопросу.)

Итак, первое предупреждение V547 печатается, потому что переменная без знака не может быть меньше нуля. Также не имеет значения, какое значение имеет переменная.
Второе предупреждение выдается, потому что анализатор реагирует на то, что переменной i присвоено значение 0, и эта переменная нигде не изменяется.

Теперь давайте напишем еще один тестовый пример, чтобы анализатор ничего не знал о значении переменной i:

void F2(size_t i)
{
std::wstring s;
s = (i < 0)   ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
}

Теперь будет только одно предупреждение V547:

  • V547 Expression ‘I < 0 ‘всегда ложно. Значение типа без знака никогда не бывает < 0. consoleapplication1.cpp 22

Анализатор ничего не может сказать о (i != -1) состояние. Это совершенно нормально, и это может быть, например, сравнение с npos, как уже заметили.

Я написал это на тот случай, если кто-то решит протестировать исходный пример с помощью PVS-Studio, исключив его. Этот человек будет удивлен, когда увидит два предупреждения, хотя обсуждается, что будет только одно.

1
По вопросам рекламы [email protected]