Variables and fundamental types

C++ · Essentials · 12 min

C++ makes you choose types explicitly, and the rules for sizes, overflow and conversions cause real bugs if you don't know them.

A variable has a type fixed at compile time: int count = 0;. The fundamental types are:

  • Integers: short, int, long, long long, each with an unsigned variant. The standard only guarantees minimum widths (int at least 16 bits, long long at least 64); on every mainstream platform int is 32 bits.
  • std::size_t: unsigned, the type of sizes and indexes (sizeof, .size()).
  • Exact widths from <cstdint>: std::int32_t, std::uint64_t, ... for file formats and protocols.
  • Floating point: float (32-bit), double (64-bit, the default for literals like 1.5).
  • bool (true/false) and char (one byte, holds a character such as 'A').

sizeof(T) gives a size in bytes and std::numeric_limits<T> (header <limits>) gives ranges. Literals can use digit separators (1'000'000) and suffixes (2.5f is a float, 10u unsigned, 10LL long long).

Know the arithmetic rules. Integer division truncates: 7 / 2 is 3; make one operand a double (7 / 2.0) for 3.5. Unsigned arithmetic wraps around modulo 2^N, so 0u - 1 is a huge number. Signed overflow is undefined behaviour: the compiler assumes it never happens, and the result is not guaranteed to wrap.

A local variable without an initializer, like int x;, holds garbage, and reading it is undefined behaviour. Initialize every variable when you declare it. Use const for values that never change: const double tax_rate = 0.2;.

Example

#include <cstdint>
#include <iostream>
#include <limits>

int main() {
    int count = 42;                 // usually 32 bits
    long long big = 9'000'000'000;  // at least 64 bits
    double price = 19.99;           // 64-bit floating point
    float ratio = 0.5f;             // f suffix: float literal
    bool done = false;
    char letter = 'A';
    std::int32_t exact = -7;        // exactly 32 bits, from <cstdint>
    unsigned int u = 0;

    std::cout << sizeof(int) << ' ' << sizeof(long long) << '\n';   // 4 8 (typical)
    std::cout << std::numeric_limits<int>::max() << '\n';           // 2147483647
    std::cout << 7 / 2 << ' ' << 7 / 2.0 << '\n';                   // 3 3.5
    std::cout << u - 1 << '\n';                                     // 4294967295: wraps
    std::cout << count + exact << ' ' << big << ' ' << price * ratio
              << ' ' << done << ' ' << letter << '\n';              // 35 9000000000 9.995 0 A
}

Remember

  • Sizes are platform-dependent; use <cstdint> types when the exact width matters
  • Integer division truncates; unsigned wraps; signed overflow is undefined behaviour
  • Always initialise variables when you declare them

Watch out for

  • Reading an uninitialised local (int x; x++;) — it is undefined behaviour, not zero.

Check yourself

  1. What does `int r = 9 / 4 * 2.0;` store in r?
  2. Which statement about `int` overflow, as in INT_MAX + 1, is correct?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: en.cppreference.com/w/cpp/language/types

Variables and fundamental types · C++ · Topolearn