cpp

examples

examples.cpp⚙️
/**
 * Pointers in C++ - Comprehensive Examples
 * 
 * Demonstrates:
 * - Pointer declaration and initialization
 * - Pointer operators (& and *)
 * - Pointer arithmetic
 * - Pointers and arrays
 * - Pointers to pointers
 * - const with pointers
 * 
 * Compile: g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
 * Run: ./examples
 */

#include <iostream>
#include <string>
#include <cstdint>

using namespace std;

// ============================================================
// SECTION 1: POINTER BASICS
// ============================================================

void demonstrateBasicPointers() {
    cout << "--- Basic Pointer Concepts ---\n" << endl;
    
    // Variable declaration
    int x = 42;
    
    // Pointer declaration and initialization
    int* ptr = &x;  // ptr holds address of x
    
    cout << "Variable x:" << endl;
    cout << "  Value: " << x << endl;
    cout << "  Address (&x): " << &x << endl;
    cout << "  Size: " << sizeof(x) << " bytes" << endl;
    
    cout << "\nPointer ptr:" << endl;
    cout << "  Value (address it holds): " << ptr << endl;
    cout << "  Dereferenced (*ptr): " << *ptr << endl;
    cout << "  Address of ptr (&ptr): " << &ptr << endl;
    cout << "  Size: " << sizeof(ptr) << " bytes" << endl;
    
    // Modifying through pointer
    *ptr = 100;
    cout << "\nAfter *ptr = 100:" << endl;
    cout << "  x = " << x << endl;
    cout << "  *ptr = " << *ptr << endl;
}

void demonstratePointerTypes() {
    cout << "\n--- Different Pointer Types ---\n" << endl;
    
    int intVar = 42;
    double doubleVar = 3.14159;
    char charVar = 'A';
    bool boolVar = true;
    
    int* intPtr = &intVar;
    double* doublePtr = &doubleVar;
    char* charPtr = &charVar;
    bool* boolPtr = &boolVar;
    
    cout << "int* points to " << *intPtr << " at " << intPtr << endl;
    cout << "double* points to " << *doublePtr << " at " << doublePtr << endl;
    cout << "char* points to '" << *charPtr << "' at " << static_cast<void*>(charPtr) << endl;
    cout << "bool* points to " << boolalpha << *boolPtr << " at " << boolPtr << endl;
    
    cout << "\nPointer sizes on this system:" << endl;
    cout << "  sizeof(int*): " << sizeof(intPtr) << " bytes" << endl;
    cout << "  sizeof(double*): " << sizeof(doublePtr) << " bytes" << endl;
    cout << "  sizeof(char*): " << sizeof(charPtr) << " bytes" << endl;
    cout << "  sizeof(void*): " << sizeof(void*) << " bytes" << endl;
}

void demonstrateNullptr() {
    cout << "\n--- nullptr Demonstration ---\n" << endl;
    
    int* ptr = nullptr;  // Modern C++ way
    
    cout << "ptr initialized to nullptr" << endl;
    cout << "ptr value: " << ptr << endl;
    
    // Check before dereferencing
    if (ptr == nullptr) {
        cout << "ptr is null - safe check passed" << endl;
    }
    
    // Alternative check using boolean conversion
    if (!ptr) {
        cout << "ptr is null - boolean check passed" << endl;
    }
    
    // Now assign a valid address
    int x = 42;
    ptr = &x;
    
    if (ptr != nullptr) {
        cout << "\nptr now points to value: " << *ptr << endl;
    }
}

// ============================================================
// SECTION 2: POINTER ARITHMETIC
// ============================================================

void demonstratePointerArithmetic() {
    cout << "\n--- Pointer Arithmetic ---\n" << endl;
    
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr;  // Points to arr[0]
    
    cout << "Array: 10, 20, 30, 40, 50" << endl;
    cout << "Initial ptr points to: " << *ptr << " at " << ptr << endl;
    
    // Increment
    ptr++;
    cout << "\nAfter ptr++:" << endl;
    cout << "  ptr points to: " << *ptr << " at " << ptr << endl;
    
    // Add offset
    ptr += 2;
    cout << "\nAfter ptr += 2:" << endl;
    cout << "  ptr points to: " << *ptr << " at " << ptr << endl;
    
    // Decrement
    ptr--;
    cout << "\nAfter ptr--:" << endl;
    cout << "  ptr points to: " << *ptr << " at " << ptr << endl;
    
    // Reset and show arithmetic
    ptr = arr;
    cout << "\nPointer arithmetic with different offsets:" << endl;
    for (int i = 0; i < 5; i++) {
        cout << "  *(ptr + " << i << ") = " << *(ptr + i) << endl;
    }
}

void demonstratePointerSizeArithmetic() {
    cout << "\n--- Pointer Size-Aware Arithmetic ---\n" << endl;
    
    char charArr[] = {'A', 'B', 'C', 'D', 'E'};
    int intArr[] = {1, 2, 3, 4, 5};
    double doubleArr[] = {1.1, 2.2, 3.3, 4.4, 5.5};
    
    char* charPtr = charArr;
    int* intPtr = intArr;
    double* doublePtr = doubleArr;
    
    cout << "char* increment (sizeof char = " << sizeof(char) << "):" << endl;
    cout << "  charPtr: " << static_cast<void*>(charPtr) << endl;
    charPtr++;
    cout << "  charPtr + 1: " << static_cast<void*>(charPtr) << " (moved " << sizeof(char) << " byte)" << endl;
    
    cout << "\nint* increment (sizeof int = " << sizeof(int) << "):" << endl;
    cout << "  intPtr: " << intPtr << endl;
    intPtr++;
    cout << "  intPtr + 1: " << intPtr << " (moved " << sizeof(int) << " bytes)" << endl;
    
    cout << "\ndouble* increment (sizeof double = " << sizeof(double) << "):" << endl;
    cout << "  doublePtr: " << doublePtr << endl;
    doublePtr++;
    cout << "  doublePtr + 1: " << doublePtr << " (moved " << sizeof(double) << " bytes)" << endl;
}

void demonstratePointerSubtraction() {
    cout << "\n--- Pointer Subtraction ---\n" << endl;
    
    int arr[] = {10, 20, 30, 40, 50};
    int* start = arr;
    int* end = arr + 4;  // Points to last element
    
    cout << "start points to arr[0]: " << *start << endl;
    cout << "end points to arr[4]: " << *end << endl;
    
    ptrdiff_t diff = end - start;
    cout << "\nend - start = " << diff << " elements" << endl;
    
    // Pointer comparison
    cout << "\nPointer comparison:" << endl;
    cout << "  start < end: " << boolalpha << (start < end) << endl;
    cout << "  start == end: " << (start == end) << endl;
}

// ============================================================
// SECTION 3: POINTERS AND ARRAYS
// ============================================================

void demonstrateArrayPointerRelationship() {
    cout << "\n--- Array-Pointer Relationship ---\n" << endl;
    
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr;  // Array decays to pointer
    
    cout << "Array: {10, 20, 30, 40, 50}" << endl;
    cout << "\narr = " << arr << " (array decays to address)" << endl;
    cout << "&arr[0] = " << &arr[0] << " (same address)" << endl;
    cout << "ptr = " << ptr << " (same address)" << endl;
    
    cout << "\nEquivalent access methods:" << endl;
    for (int i = 0; i < 5; i++) {
        cout << "  arr[" << i << "] = " << arr[i];
        cout << ", *(arr + " << i << ") = " << *(arr + i);
        cout << ", ptr[" << i << "] = " << ptr[i];
        cout << ", *(ptr + " << i << ") = " << *(ptr + i) << endl;
    }
}

void demonstrateArrayVsPointerDifference() {
    cout << "\n--- Array vs Pointer Difference ---\n" << endl;
    
    int arr[5] = {1, 2, 3, 4, 5};
    int* ptr = arr;
    
    cout << "sizeof(arr) = " << sizeof(arr) << " bytes (whole array)" << endl;
    cout << "sizeof(ptr) = " << sizeof(ptr) << " bytes (just pointer)" << endl;
    
    cout << "\nNumber of elements using sizeof:" << endl;
    cout << "  sizeof(arr) / sizeof(arr[0]) = " << sizeof(arr) / sizeof(arr[0]) << endl;
    
    // Can modify pointer, not array name
    cout << "\nPointer can be modified:" << endl;
    cout << "  Original ptr points to: " << *ptr << endl;
    ptr++;
    cout << "  After ptr++, points to: " << *ptr << endl;
    
    // arr++; // This would cause a compile error!
    cout << "  arr++ would cause compile error (array name is not modifiable)" << endl;
}

// Function that takes array (actually takes pointer)
void printArray(int* arr, int size) {
    cout << "Array elements: ";
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

void demonstrateArrayParameter() {
    cout << "\n--- Arrays as Function Parameters ---\n" << endl;
    
    int numbers[] = {5, 10, 15, 20, 25};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    cout << "Calling printArray with int array:" << endl;
    printArray(numbers, size);
    
    // Can also pass pointer directly
    int* ptr = numbers;
    cout << "\nCalling printArray with int pointer:" << endl;
    printArray(ptr, size);
}

// ============================================================
// SECTION 4: POINTERS TO POINTERS
// ============================================================

void demonstratePointerToPointer() {
    cout << "\n--- Pointer to Pointer ---\n" << endl;
    
    int x = 42;
    int* ptr = &x;       // Pointer to int
    int** pptr = &ptr;   // Pointer to pointer to int
    int*** ppptr = &pptr; // Pointer to pointer to pointer to int
    
    cout << "int x = 42" << endl;
    cout << "int* ptr = &x" << endl;
    cout << "int** pptr = &ptr" << endl;
    cout << "int*** ppptr = &pptr" << endl;
    
    cout << "\nAccessing value through different levels:" << endl;
    cout << "  x = " << x << endl;
    cout << "  *ptr = " << *ptr << endl;
    cout << "  **pptr = " << **pptr << endl;
    cout << "  ***ppptr = " << ***ppptr << endl;
    
    cout << "\nAddresses at each level:" << endl;
    cout << "  &x = " << &x << endl;
    cout << "  ptr = " << ptr << " (holds &x)" << endl;
    cout << "  &ptr = " << &ptr << endl;
    cout << "  pptr = " << pptr << " (holds &ptr)" << endl;
    cout << "  &pptr = " << &pptr << endl;
    cout << "  ppptr = " << ppptr << " (holds &pptr)" << endl;
}

// Function that modifies a pointer
void allocateInt(int** pptr, int value) {
    *pptr = new int(value);
}

void demonstrateModifyingPointerViaPointer() {
    cout << "\n--- Modifying Pointer via Pointer-to-Pointer ---\n" << endl;
    
    int* ptr = nullptr;
    cout << "Before allocateInt: ptr = " << ptr << endl;
    
    allocateInt(&ptr, 42);
    cout << "After allocateInt: ptr = " << ptr << ", *ptr = " << *ptr << endl;
    
    delete ptr;
    ptr = nullptr;
    cout << "After cleanup: ptr = " << ptr << endl;
}

// ============================================================
// SECTION 5: CONST WITH POINTERS
// ============================================================

void demonstrateConstPointers() {
    cout << "\n--- const with Pointers ---\n" << endl;
    
    int x = 10;
    int y = 20;
    
    // 1. Pointer to non-const
    cout << "1. int* ptr (non-const pointer to non-const int)" << endl;
    int* ptr1 = &x;
    *ptr1 = 15;    // OK: can modify data
    ptr1 = &y;     // OK: can change pointer
    cout << "   Can modify data and change pointer" << endl;
    
    // 2. Pointer to const
    cout << "\n2. const int* ptr (pointer to const int)" << endl;
    const int* ptr2 = &x;
    // *ptr2 = 15;  // ERROR: can't modify data
    ptr2 = &y;     // OK: can change pointer
    cout << "   Cannot modify data, can change pointer" << endl;
    cout << "   *ptr2 = " << *ptr2 << endl;
    
    // 3. Const pointer
    cout << "\n3. int* const ptr (const pointer to int)" << endl;
    int* const ptr3 = &x;
    *ptr3 = 25;    // OK: can modify data
    // ptr3 = &y;  // ERROR: can't change pointer
    cout << "   Can modify data, cannot change pointer" << endl;
    cout << "   *ptr3 = " << *ptr3 << endl;
    
    // 4. Const pointer to const
    cout << "\n4. const int* const ptr (const pointer to const int)" << endl;
    const int* const ptr4 = &x;
    // *ptr4 = 35;  // ERROR: can't modify data
    // ptr4 = &y;   // ERROR: can't change pointer
    cout << "   Cannot modify data, cannot change pointer" << endl;
    cout << "   *ptr4 = " << *ptr4 << endl;
}

void demonstrateConstUseCases() {
    cout << "\n--- Practical const Pointer Uses ---\n" << endl;
    
    // Pointer to const is useful for read-only access
    string message = "Hello, World!";
    const char* strPtr = message.c_str();
    
    cout << "Read-only string access:" << endl;
    cout << "  Message: " << strPtr << endl;
    // strPtr[0] = 'h';  // ERROR: can't modify through const char*
    
    // Array of const pointers to const strings
    const char* const days[] = {
        "Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday"
    };
    
    cout << "\nDays of the week:" << endl;
    for (int i = 0; i < 7; i++) {
        cout << "  " << days[i] << endl;
    }
}

// ============================================================
// SECTION 6: VOID POINTERS
// ============================================================

void demonstrateVoidPointer() {
    cout << "\n--- void Pointers (Generic Pointers) ---\n" << endl;
    
    int intVal = 42;
    double doubleVal = 3.14;
    char charVal = 'X';
    
    void* vptr;
    
    // Can point to any type
    vptr = &intVal;
    cout << "void* pointing to int: " << *static_cast<int*>(vptr) << endl;
    
    vptr = &doubleVal;
    cout << "void* pointing to double: " << *static_cast<double*>(vptr) << endl;
    
    vptr = &charVal;
    cout << "void* pointing to char: " << *static_cast<char*>(vptr) << endl;
    
    cout << "\nNote: Must cast void* before dereferencing!" << endl;
}

// ============================================================
// SECTION 7: POINTER BEST PRACTICES
// ============================================================

void demonstrateBestPractices() {
    cout << "\n--- Pointer Best Practices ---\n" << endl;
    
    // 1. Always initialize pointers
    cout << "1. Always initialize pointers:" << endl;
    int* ptr1 = nullptr;  // Good
    cout << "   int* ptr = nullptr; ✓" << endl;
    
    // 2. Check before dereferencing
    cout << "\n2. Check for null before dereferencing:" << endl;
    if (ptr1 != nullptr) {
        cout << "   Safe to use" << endl;
    } else {
        cout << "   Pointer is null - don't dereference! ✓" << endl;
    }
    
    // 3. Set to nullptr after delete
    cout << "\n3. Set to nullptr after delete:" << endl;
    int* ptr2 = new int(42);
    delete ptr2;
    ptr2 = nullptr;  // Good practice
    cout << "   delete ptr; ptr = nullptr; ✓" << endl;
    
    // 4. Use references when possible
    cout << "\n4. Prefer references for non-null, non-reassignable cases:" << endl;
    int value = 100;
    int& ref = value;  // Can't be null, can't be reassigned
    cout << "   int& ref = value; ✓ (safer than pointer)" << endl;
}

// ============================================================
// MAIN FUNCTION
// ============================================================

int main() {
    cout << "╔════════════════════════════════════════════════════════════════════╗" << endl;
    cout << "║                   C++ POINTERS - EXAMPLES                          ║" << endl;
    cout << "║              Memory Addresses and Indirection                      ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════════════╝" << endl;
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 1: Pointer Basics                       ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstrateBasicPointers();
    demonstratePointerTypes();
    demonstrateNullptr();
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 2: Pointer Arithmetic                   ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstratePointerArithmetic();
    demonstratePointerSizeArithmetic();
    demonstratePointerSubtraction();
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 3: Pointers and Arrays                  ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstrateArrayPointerRelationship();
    demonstrateArrayVsPointerDifference();
    demonstrateArrayParameter();
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 4: Pointers to Pointers                 ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstratePointerToPointer();
    demonstrateModifyingPointerViaPointer();
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 5: const with Pointers                  ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstrateConstPointers();
    demonstrateConstUseCases();
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 6: void Pointers                        ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstrateVoidPointer();
    
    cout << "\n╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              SECTION 7: Best Practices                       ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    demonstrateBestPractices();
    
    cout << "\n╔════════════════════════════════════════════════════════════════════╗" << endl;
    cout << "║                       Examples Complete!                           ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════════════╝" << endl;
    
    return 0;
}
Examples - C++ Tutorial | DeepML