long long in C/C++
Asked Answered
D

5

90

I am trying this code on GNU's C++ compiler and am unable to understand its behaviour:

#include <stdio.h>;

int main()
{
    int  num1 = 1000000000;
    long num2 = 1000000000;
    long long num3;
    //num3 = 100000000000;
    long long num4 = ~0;

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3));
    printf("%d %ld %lld %llu", num1, num2, num3, num4);
    return 0;
}

When I uncomment the commented line, the code doesn't compile and is giving an error:

error: integer constant is too large for long type

But, if the code is compiled as it is and is executed, it produces values much larger than 10000000000.

Why?

Duren answered 22/9, 2009 at 9:1 Comment(3)
May be too late now but for future readers, I suggest you use <stdint.h> and use uint64_t. To display a 64 bit value, printf( "%" PRIu64 "\n", val);Varietal
@Varietal <stdint.h> included, uint64_t a = 0xffffffffffffff; printf( "%" PRIu64 "\n",a ); : error: expected ‘)’ before ‘PRIu64’ printf( "%" PRIu64 "\n",a ); :: warning: spurious trailing ‘%’ in format [-Wformat=] printf( "%" PRIu64 "\n",a );Changeable
#define __STDC_FORMAT_MACROS 1 See #14536056Varietal
L
155

The letters 100000000000 make up a literal integer constant, but the value is too large for the type int. You need to use a suffix to change the type of the literal, i.e.

long long num3 = 100000000000LL;

The suffix LL makes the literal into type long long. C is not "smart" enough to conclude this from the type on the left, the type is a property of the literal itself, not the context in which it is being used.

Lemons answered 22/9, 2009 at 9:2 Comment(3)
Back when this answer was written it was probably correct, but now the C++ standard says that the type of an integer literal with no suffix is the first of int, long int, and long long int in which its value can be represented. [C++ §2.14.2/2] Therefore now there's no need to add the 'LL' suffix onto an integer literal that's too big for other types.Lottie
The reason this was a problem before wasn't because C++ wasn't 'smart' enough to determine the literal type from the type of the variable being assigned to, it would simply have been because the compiler extension didn't implement the extended integer type such that it would work well with the standard language. C++ now has rules such that any extended integer types will integrate better with the standard: open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdfLottie
@Lemons I think the answer should be edited according to these suggestions.Retention
R
28

Try:

num3 = 100000000000LL;

And BTW, in C++ this is a compiler extension, the standard does not define long long, thats part of C99.

Regina answered 22/9, 2009 at 9:3 Comment(1)
Well, C++11 now defines long longLoria
P
6

It depends in what mode you are compiling. long long is not part of the C++ standard but only (usually) supported as extension. This affects the type of literals. Decimal integer literals without any suffix are always of type int if int is big enough to represent the number, long otherwise. If the number is even too big for long the result is implementation-defined (probably just a number of type long int that has been truncated for backward compatibility). In this case you have to explicitly use the LL suffix to enable the long long extension (on most compilers).

The next C++ version will officially support long long in a way that you won't need any suffix unless you explicitly want the force the literal's type to be at least long long. If the number cannot be represented in long the compiler will automatically try to use long long even without LL suffix. I believe this is the behaviour of C99 as well.

Palestra answered 22/9, 2009 at 9:56 Comment(0)
P
2

your code compiles here fine (even with that line uncommented. had to change it to

num3 = 100000000000000000000;

to start getting the warning.

Pacheco answered 22/9, 2009 at 9:5 Comment(6)
What compiler? In C++, an integer literal is the smaller of int or long that it fits in. In C99, it's the smallest of int, long, long long. So when bolting long long on to C++ as a non-standard extension, perhaps your compiler has also adopted the C99 rules for literals.Hue
gcc version 4.3.2 (Debian 4.3.2-1.1) on a 64bit linux system.Pacheco
@SteveJessop A bit late perhaps: but long is NOT necessarily 64 bits. Most of the time it is, but you have no guarantees it will be everywhere. The only guarantee you have is that it is at least as big as an int, which in turn is at least as big as a short int, which in turn is at least as big as a char. Finally, char is defined as big enough to represent every character in the implementation's basic charset (typically 8-bits).Dissolute
@pauluss86: I wasn't talking about guarantees. Omry said that he was using gcc 4.3.2 on a 64 bit Debian system. I observed that this explained what he was seeing since (I happened to know as a matter of general knowledge) gcc is configured by default on such systems to use a 64 bit long in line with that OS's LP64 ABI.Hue
@SteveJessop I'm not suggesting your comment is wrong! Only pointing out that the assumption that a long is always 64 bits everywhere, which unfortunately a lot of people think, is dangerous.Dissolute
@pauluss86: right, in particular long is 32 bits wide on Windows. So whoever these people are, if they weren't recently programming Java I don't think they have much excuse for their mistake :-)Hue
S
0

Note:

  1. remove semicolon after the header file
  2. use %lu instead of just %u
  3. long long num3 = 100000000000LL;

Replace these things and you are good to go :)

Smitherman answered 1/7, 2021 at 14:20 Comment(1)
Your second point isn't correct. OP's uses of %u coincide with the result of sizeof(...) -- which is std::size_t; the correct format specifier for size_t is %zu. Also, this question has been adequately answered for over 10 years, and this answer does not expand or provide any different details to OP's question (actually, it provides less information).Gaiety

© 2022 - 2024 — McMap. All rights reserved.