Artur
Artur

Reputation: 7257

C++ integer constant's type

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

Answers (3)

user1084944
user1084944

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

aschepler
aschepler

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

Sneftel
Sneftel

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

Related Questions