Beginner's Guide
    First Steps
    Input & Output
    Custom Types – Part 1
    Diagnostics
    Standard Library
    Code Organization
    Custom Types – Part 2
    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 C++14
    long l2 = 512'232'697'499; // ' separator C++14

    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; C++11
    
    double d3 = 512'232'697'499.052; // ' separator C++14

    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

    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
    (a <=> b) < 0 if a < b
    (a <=> b) > 0 if a > b
    (a <=> b) == 0 if a and b are equal/equivalent

    3-way comparisons return a comparison category value that can be compared to literal 0.

    The returned value comes from one of three possible categories: std::strong_ordering, std::weak_ordering or std::partial_ordering.

    4 <=> 6 → std::strong_ordering::less
    5 <=> 5 → std::strong_ordering::equal
    8 <=> 1 → std::strong_ordering::greater

    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
    • 0 is always
    • everything else is true
    bool f = 12;   // true   (int → bool)
    bool g = 0;    // false  (int → bool)
    bool h = 1.2;  // true   (double → bool)

    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
    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!