How do I define a constant equal to -2147483648?

2019-01-29 07:46发布

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;

2条回答
爷、活的狠高调
2楼-- · 2019-01-29 08:08

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)

查看更多
Summer. ? 凉城
3楼-- · 2019-01-29 08:14

An unsuffixed decimal integer literal like 2147483648 is of type int, long int, or long 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 type long int or long 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, or unsigned long int (there was no type long long). So under C90 rules, 2147483648 would likely be of type unsigned long int. Applying the unary - operator to it doesn't change the type, and under the rules of unsigned arithmetic the result is 2147483648.

Although the rule that such a literal is of type int or long 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 the unsigned long int value 2147483648 will be implicitly converted to int. The result of such a conversion (when the value exceeds INT_MAX is implementation-defined, but is very likely to be -2147483648, which is INT_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 and INT_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.

查看更多
登录 后发表回答