I have a chunk of code generated by a script, and the code involves some integer constants. I ran into a strange problem: one of the constants is equal to -2147483648 (minimum signed int32), and Visual Studio generates the following error: unary minus operator applied to unsigned type, result still unsigned
(which is especially strange since I don't have treat warnings as errors enabled).
Apparently it sees an integer that doesn't fit in the signed type, makes it unsigned, and only then applies the unary minus. I suppose the result would still be correct as it will be casted to int
(which is actually a template argument), but I'd like to avoid the warning. Is it just a VS feature or does the standard have anything to say about it?
Here's the offending line:
typedef Proto_Int<-2147483648,32> Typeinfo_77;
In C++ negative numbers are stored as positive number with (-) negative sign.
That is why min int is defined as,
#define INT_MIN (-2147483647 - 1)
For int C++ does not understand 2147483648. So if possible you can also write 2147483648 as (-2147483647 - 1)
An unsuffixed decimal integer literal like
2147483648
is of typeint
,long int
, orlong long int
, specifically the first of those types in which its value can be represented.On a system with 32-bit
int
,2147483648
will be of typelong int
orlong long int
.But your compiler's warning message indicates that it's following a different set of rules. In the 1990 C standard, an unsuffixed decimal integer constant is of type
int
,long int
, orunsigned long int
(there was no typelong long
). So under C90 rules,2147483648
would likely be of typeunsigned long int
. Applying the unary-
operator to it doesn't change the type, and under the rules of unsigned arithmetic the result is2147483648
.Although the rule that such a literal is of type
int
orlong int
is present in the 1998, 2003, and 2011 ISO C++ standards, you seem to be using a compiler that behaves inconsistently with any of those standards.If your template expects an
int
, then theunsigned long int
value2147483648
will be implicitly converted toint
. The result of such a conversion (when the value exceedsINT_MAX
is implementation-defined, but is very likely to be-2147483648
, which isINT_MIN
for a 32-bit 2's-complement system.You say the C++ source is generated by a Python script, and that the value isn't necessarily
-2147483648
. I think you'll just have to add a special case so that the value-2147483648
is generated as(-2147483647-1)
. (I do recommend the parentheses; they're not necessary in this particular case, but they're harmless and can avoid operator precedence problems if you generate similar constants in other contexts.)Note that the values of
INT_MIN
andINT_MAX
can vary for different implementations. If you might need to target different C++ implementations, you should probably make your Python script smart enough to deal with different bounds.