views:

112

answers:

2

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?

+5  A: 

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 trick here is that gcc is pretty good at generating warnings, but it defaults to not doing so for sometimes unexpected cases.

unwind
+4  A: 

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.

AndreyT
Hey, good catch. `printf("%d", y);` is in a whole other category than `y=-30;`.
Pascal Cuoq
Great point, I could imagine using a negative value to create a desired bitfield, for example.
maerics