I'm puzzled by a difference in behavior between MSVC and clang for this code:
#include <iostream>
#include <cstdint>
int main() {
int64_t wat = -2147483648;
std::cout << "0x" << std::hex << wat << std::endl;
return 0;
}
Visual Studio 2010, 2012, and 2013 (on Windows 7) all display:
0x80000000
But clang 503.0.40 (on OSX) displays:
0xffffffff80000000
What is the correct behavior according to the C++ standard? Should the literal be zero-extended or sign-extended to 64 bits?
I'm aware that int64_t wat = -2147483648LL;
will lead to that same result on both compilers, but I wonder about the proper behavior without the literal suffix.
A 64-bit signed integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). A 64-bit unsigned integer. It has a minimum value of 0 and a maximum value of (2^64)-1 (inclusive).
Integer literals are numbers that do not have a decimal point or an exponential part. They can be represented as: Decimal integer literals. Hexadecimal integer literals.
Microsoft C/C++ features support for sized integer types. You can declare 8-, 16-, 32-, or 64-bit integer variables by using the __intN type specifier, where N is 8, 16, 32, or 64.
64-bit unsigned integer type is used to store only pozitiv whole number. 64-bit unsigned integer and his value range: from 0 to 18446744073709551615.
The type on the left of the initialization does not matter. The expression -2147483648
is interpreted by itself, independently.
Literal 2147483648
has no suffixes, which means that the compiler will first make an attempt to interpret it as an int
value. On your platform int
is apparently a 32-bit type. Value 2147483648
falls outside the range of signed 32-bit integer type. The compiler is required to use wider signed integer type to represent the value, if one is available (in the int
, long int
, long long int
sequence, with the last one being formally available from C++11 on). But if no sufficiently wide signed integer type is available, the behavior is undefined
In MSVC historically long int
has the same width as int
, albeit 64-bit long long int
is also supported in later versions of MSVC. However, even in VS2013 (which supports long long int
) I get
warning C4146: unary minus operator applied to unsigned type, result still unsigned
in response to your initialization. This means that MSVC still sticks to archaic C89/90 rules of integer literal interpretation (where types were chosen from int
, long int
, unsigned long int
sequence).
Note that MSVC is not officially a C++11 compiler. So formally it does not have to try long long int
. Such type does not formally exist in pre-C++11 language. From that point of view, MSVC has no sufficiently large signed integer type to use in this case and the behavior is undefined. Within the freedom provided by undefined behavior, the use of C89/90 rules for integer literal interpretation is perfectly justifiable.
You might also take a look at this (-2147483648> 0) returns true in C++?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With