7

Do literal expressions have types too ?

long long int a = 2147483647+1 ;
long long int b = 2147483648+1 ; 
std::cout << a << ',' << b ; // -2147483648,2147483649
Abhinav Vishak
  • 281
  • 5
  • 15

2 Answers2

12

Yes, literal numbers have types. The type of an unsuffixed decimal integer literal is the first of int, long, long long in which the integer can be represented. The type of binary, hex and octal literals is selected similarly but with unsigned types in the list as well.

You can force the use of unsigned types by using a U suffix. If you use a single L in the suffix then the type will be at least long but it might be long long if it cannot be represented as a long. If you use LL, then the type must be long long (unless the implementation has extended types wider than long long).

The consequence is that if int is a 32-bit type and long is 64 bits, then 2147483647 has type int while 2147483648 has type long. That means that 2147483647+1 will overflow (which is undefined behaviour), while 2147483648+1 is simply 2147483649L.

This is defined by §2.3.12 ([lex.icon]) paragraph 2 of the C++ standard, and the above description is a summary of Table 7 from that section.

It's important to remember that the type of the destination of the assignment does not influence in any way the value of the expression on the right-hand side of the assignment. If you want to force a computation to have a long long result you need to force some argument of the computation to be long long; just assigning to a long long variable isn't enough:

long long a = 2147483647 + 1LL;
std::cout << a << '\n';

produces

2147483648

(live on coliru)

rici
  • 201,785
  • 23
  • 193
  • 283
  • Is it an obligation to use the smallest integer type in which it can be represented? Can you provide a citation? – m7913d Mar 19 '17 at 21:29
  • 2
    @m7913d: Yes, the standard says exactly "first of the corresponding list". I added the citation. (It's not the smallest integer type in which it can be represented; it will not be `char` or `short`, ever.) – rici Mar 19 '17 at 21:31
  • @rici: It is worth noting that a literal char, such as `'a'` will be of type `char` (unlike C, where it will be of type `int`). – rodrigo Mar 19 '17 at 21:42
  • @rodrigo, yes and a literal with a decimal point will be of type `double` :) Character literals are in a different section of the standard, with a large set of different types (for example, `u'a'` has type `char16_t`). I don't think those complications really add anything to this question, but you are free to disagree. – rici Mar 19 '17 at 21:49
  • In addition to all the above, note that the Microsoft compilers use 32-bit int and 32-bit long, so 2147483648 has type `long long`, and 2147483647L + 1 will also overflow. – Martin Bonner supports Monica Mar 20 '17 at 06:48
  • `LL` suffix for a literal that does not fit in `long long`, may get a larger extended signed integer type – M.M May 26 '20 at 20:43
  • @M.M: True. Edited. (Do you know of an applicable implementation, by the way?) – rici May 26 '20 at 21:05
  • I don't know of any. gcc does have a 128-bit extended type but declines to take up the latitude permitted by the standard to allow literals that would fit in it – M.M May 26 '20 at 21:10
  • @M.M: yep. That's pretty common, I believe. For example, ICC has wide types for use in intrinsics, but they are not extended integer types. – rici May 26 '20 at 21:31
-1
int a = INT_MAX ;
long long int b = a + 1 ; // adds 1 to a and convert it then to long long ing
long long int c = a; ++c; // convert a to long long int and increment the result with 1
cout << a << std::endl; // 2147483647
cout << b << std::endl; // -2147483648
cout << c << std::endl; // 2147483648
cout << 2147483647 + 1 << std::endl; // -2147483648 (by default integer literal is assumed to be int)
cout << 2147483647LL + 1 << std::endl; // 2147483648 (force the the integer literal to be interpreted as a long long int)

You can find more information about integer literals here.

m7913d
  • 8,353
  • 7
  • 20
  • 47
  • 3
    2147483647 may be of type `int`, but it might also be of type long. Furthermore, 2147483647 + 1 is likely to be integer overflow, which isn't -2147483648, but undefined behaviour. Finally 2147483647L + 1 can *also* overflow (and will with Microsoft compilers). – Martin Bonner supports Monica Mar 19 '17 at 21:22
  • @MartinBonner I changed my answer to use long long, which is also 64bit on Windows. Note that although it is undefined behaviour according to the c++ standard, it is almost always implemented as a 2 complement overflow and this was the behavior the OP noticed. – m7913d Mar 19 '17 at 21:33
  • @MartinBonner According to rici's answer, it should be an int (if you assume int is 32bit) – m7913d Mar 19 '17 at 21:37
  • 1
    @m7913d: I think Martin's point was that it is possible for `int` to be 16 bits while `long` must be at least 32 bits. With 16-bit `int` and 32-bit `long`, then the literal 2147483647 has type `long` (but adding one is still an overflow). – rici Mar 19 '17 at 21:52
  • 1
    It is worth knowing that integer overflow often behaves as two-complement (for debugging and predicting how a buggy program got into the state it did, but it's also worth calling out it is undefined behaviour and that *anything* can happen. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33498 where GCC turns a perfectly ordinary loop counting from 0 to 63 into an infinite loop because of integer overflow – Martin Bonner supports Monica Mar 20 '17 at 06:52
  • `a+1` causes undefined behaviour – M.M May 26 '20 at 21:39