Home > Software engineering >  Why does assigning 256 to a char raise a warning, but assigning 255 don't, but both result in i
Why does assigning 256 to a char raise a warning, but assigning 255 don't, but both result in i

Time:12-31

Consider this example:

#include <iostream>
int main()
{
    char c = 256;
    std::cout << static_cast<int>(c);
}

Raise a warning:

warning: overflow in conversion from 'int' to 'char' changes value from '256' to ''\000'' [-Woverflow]

But this:

#include <iostream>
int main()
{
    char c = 255;
    std::cout << static_cast<int>(c);
}

don't, but the std::cout in both cases doesn't print 256 and 255, so it shows char can't hold 256 and 255, but the warning only raise when the char c is 256?

You can toy around with it here

CodePudding user response:

It is important to specify whether char is signed in your example or not, but going by your link it is signed.

If you write

char c = 256;

256 has type int, so to store the value in c a conversion to char has to happen.

For signed target types such integer conversions produce the same value if it is representable in the target type. That would with the typical bit size and representation of a signed char be -128 to 127.

What happens if the source value is not representable in the target type depends on a few factors.

First, since C 20 two's-complement is guaranteed, meaning that the resulting value is guaranteed to be the unique value such that the it and the source value are equal modulo 2^n with n the bit size of the target type (typically 8 for char).

Before C 20 it was implementation-defined what happens in such a case, but it is very likely that the implementation would just have specified behavior equivalent to the C 20 one.

So, the warning is not meant to prevent undefined behavior or even implementation-defined behavior since C 20, but just to notify the user about likely mistakes.

I can't be sure why GCC chooses to warn only for values larger than 255, but my guess is that it is done because a statement like

char c = 255;

makes sense if you interpret the right-hand side as an unsigned char. The conversion rule explained above would not change the character represented before and after the conversion.

However

char c = 256;

doesn't even make sense if the right-hand side is interpreted as unsigned char. So the likelihood that this is a mistake seems higher.

But maybe I am also guessing in the wrong direction. There is an open bug report for GCC concerning this behavior of the -Woverflow warning. From reading the comments there it is not clear to me what the reasoning for the behavior was originally.

Clang for example consistently warns about all out-of-range values. So there seem to be different thoughts put into the warnings.

  • Related