Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Using VS2015

char a = 0xFF;
char b = 0x80;

Both lines give warning C4309: 'initializing': truncation of constant value

But when I look at it in the debugger, the variables do indeed contain the correct values.

What does the warning mean in this case? Can I ignore it or is my code bad?

like image 760
Neil Kirk Avatar asked Oct 25 '15 18:10

Neil Kirk


3 Answers

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;
like image 86
Alex Lop. Avatar answered Nov 19 '22 05:11

Alex Lop.


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

like image 41
Martin Franceschi Avatar answered Nov 19 '22 07:11

Martin Franceschi


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.

like image 24
TonyK Avatar answered Nov 19 '22 07:11

TonyK