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?
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 compare 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With