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.