Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

long long is a fundamental integral data type in C++ guaranteed by the standard to be at least 64 bits in width. Formalized in C++11, it provides the largest standard integer capacity natively available in the language, strictly superseding the minimum width guarantees of int (16 bits) and long (32 bits).

Memory and Range Specifications

According to the C++ standard, the exact size of long long is implementation-defined but must contain at least 64 bits. Assuming a standard 64-bit implementation (where two’s complement representation is mandated since C++20):
  • signed long long: 263-2^{63} to 26312^{63}-1 (9,223,372,036,854,775,808-9,223,372,036,854,775,808 to 9,223,372,036,854,775,8079,223,372,036,854,775,807)
  • unsigned long long: 00 to 26412^{64}-1 (00 to 18,446,744,073,709,551,61518,446,744,073,709,551,615)

Syntax and Declarations

The type can be declared with or without the int keyword, and defaults to signed unless explicitly marked unsigned.
// Signed declarations (all are equivalent)
long long var1;
signed long long var2;
long long int var3;
signed long long int var4;

// Unsigned declarations (all are equivalent)
unsigned long long var5;
unsigned long long int var6;

Literal Evaluation and Suffixes

The C++ standard dictates that the type of an unsuffixed decimal integer literal is determined by the compiler as the first type in which its value can fit from a fixed list: int, long int, or long long int. Therefore, a literal like 9223372036854775807 is evaluated as long long without requiring a suffix. However, unsuffixed base-10 literals are never determined to be standard unsigned types. If a base-10 literal exceeds the maximum value of a signed long long, the compiler will first attempt to fit the literal into an extended signed integer type (such as __int128, if supported by the implementation). The program is strictly ill-formed if the value cannot be represented by any extended integer type. The ULL suffix is used to explicitly force evaluation as an unsigned long long and bypass this fallback behavior.
// Determined to be long long; fits within signed 64-bit range
long long val1 = 9223372036854775807; 

// Exceeds signed long long max. Evaluates to an extended signed integer 
// type (e.g., __int128) if supported, otherwise the program is ill-formed.
// auto val2 = 18446744073709551615; // Uncommenting causes compilation error on MSVC/32-bit GCC

// CORRECT: 'ULL' suffix explicitly forces unsigned long long evaluation
unsigned long long val3 = 18446744073709551615ULL; 
Explicit suffixes (LL or ll for signed, ULL or ull for unsigned) are necessary in specific scenarios:
  1. Undefined Behavior and Overflow Prevention: To prevent intermediate issues before assignment. If operands are small enough to fit in an int, the arithmetic is performed as int. Shifting an int by an amount greater than or equal to its bit-width results in Undefined Behavior (UB), and multiplying large int values can result in arithmetic overflow.
  2. Type Deduction: To force the auto keyword to deduce a 64-bit type.
  3. Overload Resolution: To explicitly match a function signature expecting a long long parameter.
// 1. Undefined Behavior / Overflow Prevention
// '1 << 40' is Undefined Behavior because '1' is an int (typically 32-bit). 
// '1LL' forces 64-bit arithmetic, making the shift valid.
long long shifted = 1LL << 40; 
long long multiplied = 2000000000LL * 2;

// 2. Type Deduction
auto deduced_signed = 10LL;    // Type is long long
auto deduced_unsigned = 10ULL; // Type is unsigned long long

// 3. Overload Resolution
void process(int x);
void process(long long x);

process(5);   // Calls process(int)
process(5LL); // Calls process(long long)

Programmatic Introspection

You can query the exact byte size and numeric limits of long long on a specific architecture using the sizeof operator and the <limits> header. Note that sizeof returns the size in bytes, where a byte is defined by the standard as CHAR_BIT bits. Because CHAR_BIT can be greater than 8 on certain architectures (e.g., 16 or 32), sizeof(long long) is not guaranteed to be 8\ge 8, even though the type itself is strictly guaranteed to be 64\ge 64 bits.
#include <iostream>
#include <limits>

int main() {
    // Returns size in bytes (where 1 byte = CHAR_BIT bits)
    std::cout << sizeof(long long) << '\n'; 

    // Returns maximum representable value
    std::cout << std::numeric_limits<long long>::max() << '\n'; 

    // Returns minimum representable value
    std::cout << std::numeric_limits<long long>::min() << '\n'; 
    
    return 0;
}

Relationship to Fixed-Width Integers

In modern C++ (via the <cstdint> header), int64_t and uint64_t provide exact 64-bit width guarantees. The underlying type used by the compiler to implement these typedefs depends on the platform’s data model. On 32-bit systems and 64-bit Windows (which uses the LLP64 data model), long is 32 bits, making int64_t a typedef for long long int. However, on 64-bit Unix-like systems such as Linux and macOS (which use the LP64 data model), long is already 64 bits, meaning int64_t is typically a typedef for long int.
#include <cstdint>

// Guaranteed exactly 64 bits; typedef for 'long' or 'long long' depending on data model
int64_t exact_signed = 100LL;

// Guaranteed exactly 64 bits; typedef for 'unsigned long' or 'unsigned long long'
uint64_t exact_unsigned = 200ULL;
Master C++ with Deep Grasping Methodology!Learn More