Выражение "i < 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 например, сообщать об этом как о правде?

4 ответа

Решение

Потому что это было бы бесполезным, недействительным предупреждением. 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 скорее всего, не то, что хотел программист, и поэтому предупреждение оправдано.

Это связано с неявными интегральными преобразованиями в обоих случаях. 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

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

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

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

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

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 Выражение "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 Выражение "i <0" всегда ложно. Значение типа без знака никогда не бывает < 0. consoleapplication1.cpp 22

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

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

Другие вопросы по тегам