GCC does not warn when using == op with a signed var and an unsigned literal
Why does GCC warn only for situations 1 and 3 and not 2 in the code below ?
I'm comp开发者_StackOverflowiling with -Wall and -g flags.
int main() {
unsigned int ui = 4;
int si = 6;
if (si == ui ) { // Warning comparison b/w signed and unsigned
printf("xxxx");
}
if (si == 2U ) { // No Warning --- WHY ???
printf("xxxx");
}
if (si > 2U ) { // Warning comparison b/w signed and unsigned
printf("xxxx");
}
return 0;
}
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:
-Wconversion section:
Do not warn for explicit casts like
abs ((int) x)
andui = (unsigned) -1
, or if the value is not changed by the conversion like inabs (2.0)
.
Since 2U
is literal, gcc know that:
- if
si < 0
, then(unsigned) si >= 2^31
, therefores1 != 2U
. - if
si > 0
, then(unsigned) si
has the same value assi
, therefore(unsigned) si == 2U
if and only ifsi == 2
.
In conclusion, comparing the signed si
with literal 2U
is the same as comparing si
with 2
, i.e., the result of si == 2U
would not be changed by converting si
to unsigned
.
If you compare with 2^32-1 (4294967295U), the largest in 32-bit unsigned int, which is not representable in int
, then si
could be equal to it even if si
itself is negative, this may not be what you wanted, so a warning is generated with -Wextra
option.
Possibly because there's no ambiguity in an equality comparison with constant in the range where signed and unsigned versions of the type overlap.
If I change it to
if (si == 2147483648U ) {
printf("xxxx");
}
I get a warning
(Actually, I had to add -Wextra before I got the warnings you reported)
Chris thanks for your answer. I think it leads to the cause. My original thought was that the U suffix would cause this literal to be promoted to an unsigned type however I think that it is only promoted to an unsigned type when the number is greater than INT_MAX_32 that is > 2147483647.
精彩评论