Reputation: 7257
According to MSDN (Integer Types - VC2008):
The type for a decimal constant without a suffix is either int, long int, or unsigned long int. The first of these three types in which the constant's value can be represented is the type assigned to the constant.
Running the below code on Visual C++ 2008:
void verify_type(int a){printf("int [%i/%#x]\n", a, a);}
void verify_type(unsigned int a){printf("uint [%u/%#x]\n", a, a);}
void verify_type(long a){printf("long [%li/%#lx]\n", a, a);}
void verify_type(unsigned long a){printf("ulong [%lu/%#lx]\n", a, a);}
void verify_type(long long a){printf("long long [%lli/%#llx]\n", a, a);}
void verify_type(unsigned long long a){printf("unsigned long long [%llu/%#llx]\n", a, a);}
int _tmain(int argc, _TCHAR* argv[])
{
printf("sizeof(int) %i\n", sizeof(int));
printf("sizeof(long) %i\n", sizeof(long));
printf("sizeof(long long) %i\n\n", sizeof(long long));
verify_type(-2147483647);
verify_type(-2147483648);
getchar();
return 0;
}
I get this:
sizeof(int) 4
sizeof(long) 4
sizeof(long long) 8
int [-2147483647/0x80000001]
ulong [2147483648/0x80000000] <------ Why ulong?
I would expect const -2147483648
() to be int. Why do I get a ulong, not int?
I've been programming for quite a long time and until today I've not noticed that + or - is not part of integer constant. This one hint explained everything.
integer-constant:
decimal-constant integer-suffix<opt>
octal-constant integer-suffix<opt>
hexadecimal-constant integer-suffix<opt>
decimal-constant:
nonzero-digit
decimal-constant digit
octal-constant:
0
octal-constant octal-digit
hexadecimal-constant:
0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
octal-digit: one of
0 1 2 3 4 5 6 7
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F
integer-suffix:
unsigned-suffix long-suffix<opt>
long-suffix unsigned-suffix<opt>
unsigned-suffix: one of
u U
long-suffix: one of
l L
Upvotes: 3
Views: 959
Reputation:
You are applying the unary -
operator to the integer literal 2147483648
. The integer literal, being 2^31
is too large to fit in a 32-bit int
. In modern C++, it should have been treated as a long long
, so your result is surprising.
I believe old C standards (prior to long long
) allowed interpreting a literal too large for long
to have type unsigned long
, which is consistent with what you're seeing. I see the documentation from MSDN you quoted at the top of your post repeats this, so that's surely what's going on here.
Upvotes: 5
Reputation: 72271
-2147483648
is not an integer literal. It is the unary operator -
applied to the integer literal 2147483648
. That literal's value does not fit in a signed int
or signed long
, so it has type unsigned long
. The -
operator does not change that type.
Upvotes: 5
Reputation: 41474
First, -2147483648
is not an integer constant, because -
is a unary operator, not part of a constant (at least in that context). 2147483648
is an integer constant, and -2147483648
is an expression involving that constant.
Because 2147483648
is not representable as an int
or long int
, but is representable as an unsigned long int
, it gets the type unsigned long int
. And the result of applying the unary -
operator to an unsigned long int
is itself an unsigned long int
.
Upvotes: 5