Warning C4309 - what does it mean and can it be ignored in this case?

In VS20125, a char is signed by default, so its range is -128 to +127. To suppress the warning, declare a and b as unsigned char, with a range of 0 to 255.


I know it is an old topic, but I wanted to add a precision. In your case, you can simply put :

char a = '\xff';
char b = '\x80';

It creates a character literal (https://en.cppreference.com/w/c/language/character_constant) from a hexadecimal escape sequence (https://en.cppreference.com/w/c/language/escape). The compiler will only create a char and not an int and then you will receive no warnings.

This is valid in all version of C and C++.


From https://msdn.microsoft.com/en-us/library/sz5z1byt.aspx

'conversion' : truncation of constant value

The type conversion causes a constant to exceed the space allocated for it. You may need to use a larger type for the constant.

The following sample generates C4309:

// C4309.cpp // compile with: /W2

int main()
{
   char c = 128;   // C4309
}

The compiler assume that you expect 0xFF and 0x80 to be positive numbers. Like in the example, it is written 128 and not negative number with - sign.

So the compiler lets you know that char is a signed type of 8 bits which means your value sets the "sign bit" although it was not marked as negative.

If the sign of the variable is not important for you, use unsigned char instead. This will also remove this warning.

EDIT

In case you know what you are doing and you set the MSB bit on purpose, you can either use casting to suppress the warnings:

char a = static_cast<char>(0xFF);
char b = static_cast<char>(0x80);

Or use #pragma to disable this specific warning for these lines:

#pragma warning( disable : 4309 )
char a = 0xFF;
char b = 0x80;
#pragma warning( default : 4309 )

I personally preffer the first option since it will work for every compiler while the #pragma option is specific for MVSC.

EDIT2

Of course you can always write

char a = -1; //0xFF
char b = -128; // 0x80

But this is less readable in my opinion.

EDIT 3

The new versions of MSVC seem to complain about static_cast too. To resolve it, there is a need to specify explicitly that the provided constant number is 'unsigned':

char a = static_cast<char>(0xFFu);
char b = static_cast<char>(0x80u);

More than that, on the latest versions, no need in casting at all. This compiles without warnings:

char a = 0xFFu;
char b = 0x80u;