Home > Net >  Why is there a signedness issue when comparing uint16_t and unsigned int?
Why is there a signedness issue when comparing uint16_t and unsigned int?

Time:05-10

I have a code like this :

#include <iostream>
using std::cout;
using std::endl;

int main() {
    uint16_t a = 0;
    uint16_t b = 0;

    if ( a - b < 3u )
    {
        cout << "cacahuète" << endl;
    }
    return 0;
}

When I compile it using g with -Wall, I get :

temp.cpp: In function ‘int main()’:
temp.cpp:9:13: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
    9 |  if ( a - b < 3u )
      |       ~~~~~~^~~~

That warning doesn't show up if I write if ( a - b < static_cast<uint16_t>(3u) ) instead.

  • So what's going on, here ? Where does the int come from?
  • Can this actually result in an incorrect behavior?
  • Is there a less verbose way to silence it? (or a less verbose way to write a uint16_t literal?)

CodePudding user response:

So what's going on, here ? Where does the int come from?

Integer promotion is going on here. On systems where std::uint16_t is smaller than int, it will be promoted to int when used as an operand (of most binary operations).

In a - b both operands are promoted to int and the result is int also. You compre this signed integer to 3u which is unsigned int. The signs differ, as the compiler warns you.

That warning doesn't show up if I write if ( a - b < static_cast<uint16_t>(3u) ) instead.

Here, the right hand operand is also promoted to int. Both sides of comparison are signed so there is no warning.

Can this actually result in an incorrect behavior?

if ( a - b < static_cast<uint16_t>(3u) ) does have different behaviour than a - b < static_cast<uint16_t>(3u). If one is correct, then presumably the other is incorrect.

Is there a less verbose way to silence it? (or a less verbose way to write a uint16_t literal?)

The correct solution depends on what behaviour you want to be correct.


P.S. You forgot to include the header that defines uint16_t.

CodePudding user response:

The subtraction a - b cause the uint16_t to be promoted to int to handle the case when a < b and the result is negative.

You could rewrite this as

if (a < b   3u)

assuming b isn't close to overflowing. Or just compare it against 3 so both sides are signed.

  • Related