Several questions on this website reveal pitfalls when mixing signed and unsigned types and most compilers seem to do a good job about generating warnings of this type. However, GCC doesn't seem to care when assigning a signed constant to an unsigned type! Consider the following program:
/* foo.c */
#include <stdio.h>
int main(void)
{
unsigned int x=20, y=-30;
if (x > y) {
printf("%d > %d\n", x, y);
} else {
printf("%d <= %d\n", x, y);
}
return 0;
}
Compilation with GCC 4.2.1 as below produces no output on the console:
gcc -Werror -Wall -Wextra -pedantic foo.c -o foo
The resulting executable generates the following output:
$ ./foo
20 <= -30
Is there some reason that GCC doesn't generate any warning or error message when assigning the signed value -30
to the unsigned integer variable y
?
Conversion from signed to unsigned does not necessarily just copy or reinterpret the representation of the signed value. Quoting the C standard (C99 6.3. 1.3): When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
-Wno-coverage-invalid-line-number can be used to disable the warning or -Wno-error=coverage-invalid-line-number can be used to disable the error. Suppress warning messages emitted by #warning directives.
You can use the -Werror compiler flag to turn all or some warnings into errors.
Sure, comparisons between signed and unsigned would be slower, but their result would be more correct in some sense. @Nawaz Your bottom line conclusion is incorrect, unfortunately: if the signed type can contain the unsigned type, the unsigned will be converted to the signed type and not the opposite.
Use -Wconversion:
~/src> gcc -Wconversion -Werror -Wall -Wextra -pedantic -o signwarn signwarn.c
cc1: warnings being treated as errors
signwarn.c: In function 'main':
signwarn.c:5: error: negative integer implicitly converted to unsigned type
I guess the thing here is that gcc is actually pretty good at generating warnings, but it defaults to not doing so for (sometimes unexpected) cases. It's a good idea to browse through the available warnings and choose a set of options that generate those you feel would help. Or just all of them, and polish that code until it shines! :)
The ability to convert negative value to unsigned type is a feature of C language. For this reason, the warning is not issued by default. You have to request it explicitly, if you so desire.
As for what your program outputs... Using %d
format specifier of printf
with an unsigned value that lies beyond the range of type int
results in undefined behavior, which is what you really observed in your experiment.
Using (unsigned)-1 is an often used way to set all bits and sometimes even quoted as reason for this (mis)feature of C, even by people who should know better . It's neither obvious nor portable -- the expression you want to use to set all bits is ~0 .
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