Expression 'i < 0' is always false

4.6k Views Asked by At

For the following snippet:

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

PVS-Studio analysis logs warning for the first condition i < 0, as expected:

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

Why PVS does not issue any warning about the second, also suspicious condition i != -1 reporting it as always true, for instance?

4

There are 4 best solutions below

10
On BEST ANSWER

Because that'd be a useless, invalid warning. size_t is an unsigned type, and due to the way integer conversions work (see [conv.integral]/2), -1 converted (implicitly here) to size_t is equal to SIZE_MAX.

Consider the fact that this is the actual definition of std::string::npos in libstdc++:

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

If PVS-Studio warned about i != -1, would it also need to warn about i != std::string::npos?

On the other hand, an unsigned value can never be smaller than 0, due to it being unsigned, so i < 0 is likely not what the programmer wanted, and thus the warning is warranted.

0
On

This is due to implicit integral conversions in both cases. A size_t must be an unsigned type of at least 16 bits and in your case it is of sufficient size cf. int that if one argument is size_t and the other an int, then the int argument is converted to size_t.

When evaluating i < 0, 0 is converted to an size_t type. Both operands are size_t so the expression is always false.

When evaluating i != -1, the -1 is converted to size_t too. This value will be std::numeric_limits<size_t>::max().

Reference: http://en.cppreference.com/w/cpp/language/implicit_conversion

3
On

When a value is converted to unsigned, if that value is not representable by the unsigned type, then the value will be converted to a value (or rather, the value) that is representable, and is congruent to the original value modulo the number of representable values (which is the maximum representable value + 1 == 2n where n is the number of bits).

Therefore there is nothing to warn about, because there is some value for which the condition can be false (as long as we only analyze that expression in isolation. i is always 0, so the condition is always true, but to be able to prove that, we must take the entire execution of the program into account).

-1 is congruent with m - 1 modulo m, therefore -1 is always converted to the maximum representable value.

3
On

There were right significant answers, but I would like to make some clarifications. Unfortunately, a test example was formed incorrectly. We can write this way:

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

In such case the analyzer will issue two V547 warnings:

  • V547 Expression 'i < 0' is always false. Unsigned type value is never < 0. consoleapplication1.cpp 15
  • V547 Expression 'i != - 1' is always true. consoleapplication1.cpp 16

(V519 will also take place, but it does not relate to the issue.)

So, the first V547 warning is print because the unsigned variable cannot be less than zero. It also doesn’t matter what value the variable has. The second warning is issued because the analyzer reacts that 0 is assigned to the variable i and this variable does not change anywhere.

Now let's write another test example so that the analyzer knew nothing about the value of the variable i:

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

Now there will be only one V547 warning:

  • V547 Expression 'i < 0' is always false. Unsigned type value is never < 0. consoleapplication1.cpp 22

The analyzer can say nothing about the (i != -1) condition. It is perfectly normal and it can be, for example, the comparison with npos, as have already noticed.

I wrote this in case if someone decides to test a source example using PVS-Studio, taking it out of the question. This person will be surprised, when he sees two warnings, though it is discussed that there will be only one.