Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression 'i < 0' is always false

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?

like image 662
mloskot Avatar asked Sep 11 '25 11:09

mloskot


2 Answers

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.

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

like image 42
Bathsheba Avatar answered Sep 13 '25 00:09

Bathsheba



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!