Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't GCC produce a warning when assigning a signed literal to an unsigned type?

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?

like image 774
maerics Avatar asked May 05 '10 08:05

maerics


People also ask

What happens when you cast signed to unsigned in C?

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.

Which option of GCC inhibit all warning messages?

-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.

How do I make GCC warnings as errors?

You can use the -Werror compiler flag to turn all or some warnings into errors.

Is it suggested to compare signed and unsigned numbers in C ++?

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.


3 Answers

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! :)

like image 154
unwind Avatar answered Oct 26 '22 03:10

unwind


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.

like image 41
AnT Avatar answered Oct 26 '22 03:10

AnT


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 .

like image 2
GuentherT Avatar answered Oct 26 '22 04:10

GuentherT