Beginner's Guide
    First Steps
    Input & Output
    Basic Custom Types
    Diagnostics
    Standard Library
    Code Organization
    Powerful Custom Types
    Generic Programming
    Memory Management
    Software Design Basics

    Fundamental TypesFundamental TypesFundamental Types

    Variable Declarations Variables

    Variables of fundamental types are not initialized by default!
    int k;  // k not initialized!
    cout << k << '\n';  // value might be anything

    Because in C++ you only pay for what you use (initilization of large memory blocks can be quite expensive)

    But: You should almost always initialize variables when declaring them to prevent bugs!

    Quick Overview Overview

    bool b1 = true;
    bool b2 = false;
    • smallest integer; usually 1 byte
    • on x86/x86_64 signed ⇒ values ∈ [-128,127]
    char c = 'A';  // character literal
    char a = 65;   // same as above
    n bits ⇒ values ∈ [-2(n-1), 2(n-1)-1]
    short s = 7;        
    int   i = 12347;
    long  l1 = -7856974990l ;
    long long  l2 = 89565656974990ll;
    
    int x = 0x4A; // hexadecimal literal int b = 0b10110101; // binary literal 
    long l2 = 512'232'697'499; // ' separator 
    n bits ⇒ values ∈ [0, 2n]
    unsigned u1 = 12347u ; 
    unsigned long u2 = 123478912345ul;  
    unsigned long long u3 = 123478912345ull;
    • float usually IEEE-754 32 bit
    • double usually IEEE-754 64 bit
    • long double usually 80-bit on x86/x86-64
    float       f  = 1.88f;
    double      d1 = 3.5e38;
    long double d2 = 3.5e38l; 
    
    double d3 = 512'232'697'499.052; // ' separator 

    Arithmetic Operations Arithmetic

    • expression a ⊕ b returns result of operation ⊕ applied to the values of a and b
    • expression a ⊕= b stores result of operation ⊕ in a
    int a = 4; 
    int b = 3; 
    
    a = a + b; a += b;
    a = a b; a -= b;
    a = a * b; a *= b;
    a = a / b; a /= b;
    a = a % b;
    variable a is set to value 4
    variable b is set to value 3
    
    a: 7 add a: 10
    a: 7 subtract a: 4
    a: 12 multiply a: 36
    a: 12 divide a: 4
    a: 1 remainder of division (modulo)modulo

    Increment/Decrement Increment

    • changes value by +/- 1
    • prefix expressions ++x / --x returns new (incremented/decremented) value
    • postfix expression x++ / x-- incrementes/decrementes value, but returns old value
    int a = 4;
    int b = 3;
    
    b = a++; b = ++a;
    b = --a; b = a--;
    a: 4
            b: 3
    
    a: 5 b: 4 a: 6 b: 6
    a: 5 b: 5 a: 4 b: 5

    Comparisons

    2-way Comparisons

    result of comparison is either true or false}

    int x = 10;                       
    int y = 5;                       
    
    bool b1 = x == 5; bool b2 = (x != 6);
    bool b3 = x > y; bool b4 = x < y; bool b5 = y >= 5; bool b6 = x <= 30;
    
    result  operator
    
    false equals true not equal
    true greater false smaller true greater/equal true smaller/equal
    3-Way Comparisons With <=>
    (a <=> b) is < 0   if a < b
    (a <=> b) is == 0  if a and b are equal
    (a <=> b) is > 0   if a > b

    3-way comparisons don't actually return a number but a special comparison category object that copares less, equal or greater than 0.

    Boolean Logic

    bool a = true;
    bool b = false;
    bool c = a && b;   // false    logical AND
    bool d = a || b;   // true     logical OR
    bool e = !a;       // false    logical NOT
    Conversion to bool
    • 0 is always false
    • everything else is true
    bool f = 12;   // true   (int → bool)
    bool g = 0;    // false  (int → bool)
    bool h = 1.2;  // true   (double → bool)
    Short-circuit Evaluation

    The second operand of a boolean comparison is not evaluated if the result is already known after evaluating the first operand.

    int i = 2;  
    int k = 8;
    bool b1 = (i > 0) || (k < 3);
    i > 0 is already truek < 3 is not evaluated, because the result of logical OR is already true

    Memory Sizes of Fundamental Types Fundamental Memory Sizes Memory Sizes

    std::numeric_limits<type> std::numeric_limits numeric_limits

    #include <limits>
    // largest positive value:
    std::numeric_limits<double>::max()     
    // smallest value > 0:
    std::numeric_limits<double>::min()     
    // smallest negative value:
    std::numeric_limits<double>::lowest()  
    // smallest difference btw. 1 and next value:
    std::numeric_limits<double>::epsilon() 
    …
    #include <limits>
    std::numeric_limits<double>::max()     // largest positive value
    std::numeric_limits<double>::min()     // smallest value > 0
    std::numeric_limits<double>::lowest()  // smallest negative value
    std::numeric_limits<double>::epsilon() // smallest difference btw. 1 and next value

    Type Narrowing Narrowing

    • conversion from type that can represent more values to one that can represent less
    • may result in loss of information
    • in general no compiler warning – happens silently
    • potential source of subtle runtime bugs
    double   d = 1.23456;
    float    f = 2.53f;
    unsigned u = 120u;
    
    double e = f; // OK float → double
    int i = 2.5; // NARROWING double → int int j = u; // NARROWING unsigned int → int int k = f; // NARROWING float → int

    Braced Initialization

    type variable { value };
    • works for all fundamental types
    • narrowing conversion ⇒ compiler warning
    double   d {1.23456};  // OK
    float    f {2.53f};    // OK
    unsigned u {120u};     // OK
    
    double e {f}; // OK float → double
    int i {2.5}; // COMPILER WARNING: double → int int j {u}; // COMPILER WARNING: unsigned int → int int k {f}; // COMPILER WARNING: float → int

    Make sure to prevent silent type conversions, especially narrowing unsigned to signed integer conversions — they can cause hard-to-find runtime bugs!