S SmartDocs
Serie: C++ cpp 169 líneas · Actualizado 2026-04-03

pointers.cpp

C++/Part1_基礎入門/Ch06_指標與參考/pointers.cpp

// ============================================================
// Ch06 — 指標基礎(Pointer Basics)
// 編譯:g++ -std=c++17 -Wall -o pointers pointers.cpp
// ============================================================

#include <iostream>
#include <string>

// ── 函式原型 ──
void swapByPtr(int* a, int* b);
void printValue(const int* ptr);

// ── 主程式 ────────────────────────────────────────
int main() {
    std::cout << "===== Ch06:指標基礎 =====\n\n";

    // ── 1. 宣告與基本操作 ──
    std::cout << "【1】宣告與基本操作\n";

    int x = 42;
    int* ptr = &x;    // ptr 儲存 x 的位址

    std::cout << "x 的值      = " << x << "\n";
    std::cout << "x 的位址    = " << &x << "\n";
    std::cout << "ptr 的值    = " << ptr << "(= x 的位址)\n";
    std::cout << "*ptr(解參考)= " << *ptr << "(= x 的值)\n";
    std::cout << "ptr 自身位址 = " << &ptr << "\n\n";

    // 透過指標修改值
    *ptr = 100;
    std::cout << "執行 *ptr = 100 後:\n";
    std::cout << "x    = " << x << "\n";
    std::cout << "*ptr = " << *ptr << "\n\n";

    // ── 2. 不同型別的指標 ──
    std::cout << "【2】不同型別的指標\n";

    int    intVal = 10;
    double dblVal = 3.14;
    char   chVal  = 'A';
    bool   boolVal = true;

    int*    intPtr  = &intVal;
    double* dblPtr  = &dblVal;
    char*   chPtr   = &chVal;
    bool*   boolPtr = &boolVal;

    std::cout << "int*    指向 " << *intPtr << ",sizeof(int*)    = " << sizeof(intPtr) << "\n";
    std::cout << "double* 指向 " << *dblPtr << ",sizeof(double*) = " << sizeof(dblPtr) << "\n";
    std::cout << "char*   指向 '" << *chPtr << "',sizeof(char*)   = " << sizeof(chPtr) << "\n";
    std::cout << "bool*   指向 " << *boolPtr << ",sizeof(bool*)   = " << sizeof(boolPtr) << "\n";
    std::cout << "所有指標大小相同(通常 8 bytes on 64-bit)\n\n";

    // ── 3. nullptr ──
    std::cout << "【3】nullptr(空指標)\n";

    int* nullPtr = nullptr;

    std::cout << "nullPtr = " << nullPtr << "\n";

    if (nullPtr == nullptr) {
        std::cout << "nullPtr 是空指標 → 不能解參考!\n";
    }

    // 安全的解參考模式
    if (nullPtr != nullptr) {
        std::cout << *nullPtr << "\n";
    } else {
        std::cout << "安全檢查:跳過空指標解參考\n";
    }
    std::cout << "\n";

    // ── 4. const 指標 ──
    std::cout << "【4】const 與指標的四種組合\n";

    int a = 10, b = 20;

    // 4a. 非 const 指標,指向非 const 值
    int* p1 = &a;
    *p1 = 11;     // ✓ 可改值
    p1 = &b;      // ✓ 可改指向
    std::cout << "int* p1            → 可改值、可改指向\n";

    // 4b. 指向 const 的指標
    const int* p2 = &a;
    // *p2 = 12;  ← 錯誤!不能透過 p2 修改值
    p2 = &b;      // ✓ 可以改指向
    std::cout << "const int* p2      → 不可改值、可改指向(目前 *p2 = " << *p2 << ")\n";

    // 4c. const 指標
    int* const p3 = &a;
    *p3 = 13;     // ✓ 可改值
    // p3 = &b;   ← 錯誤!不能改指向
    std::cout << "int* const p3      → 可改值、不可改指向\n";

    // 4d. const 指標指向 const 值
    const int* const p4 = &a;
    // *p4 = 14;  ← 錯誤!
    // p4 = &b;   ← 錯誤!
    std::cout << "const int* const p4 → 不可改值、不可改指向(*p4 = " << *p4 << ")\n\n";

    // ── 5. 指標作為函式參數 ──
    std::cout << "【5】指標作為函式參數(swap 範例)\n";

    int m = 100, n = 200;
    std::cout << "交換前:m = " << m << ", n = " << n << "\n";
    swapByPtr(&m, &n);
    std::cout << "交換後:m = " << m << ", n = " << n << "\n\n";

    // const 指標參數
    std::cout << "const 指標參數(只讀存取):\n";
    int val = 999;
    printValue(&val);
    std::cout << "\n";

    // ── 6. 指標與陣列的關係(簡介) ──
    std::cout << "【6】指標與陣列的關係(簡介)\n";

    int arr[] = {10, 20, 30, 40, 50};
    int* arrPtr = arr;  // 陣列名退化為首元素指標

    std::cout << "arr     = " << arr << "\n";
    std::cout << "arrPtr  = " << arrPtr << "(相同位址)\n";
    std::cout << "arr[0]  = " << arr[0] << "\n";
    std::cout << "*arrPtr = " << *arrPtr << "(相同值)\n\n";

    for (int i = 0; i < 5; i++) {
        std::cout << "arr[" << i << "] = " << arr[i]
                  << "\t*(arrPtr + " << i << ") = " << *(arrPtr + i) << "\n";
    }
    std::cout << "\n";

    // ── 7. 動態記憶體(簡介) ──
    std::cout << "【7】動態記憶體(簡介 — 詳見 Ch16)\n";

    int* dynPtr = new int(42);
    std::cout << "new int(42) → *dynPtr = " << *dynPtr << "\n";
    std::cout << "位址:" << dynPtr << "\n";

    delete dynPtr;
    dynPtr = nullptr;
    std::cout << "delete 後將指標設為 nullptr,避免懸垂指標。\n";
    std::cout << "⚠ 現代 C++ 建議使用智慧指標(unique_ptr / shared_ptr)。\n\n";

    // ── 8. 指標大小總結 ──
    std::cout << "【8】各種指標的大小\n";
    std::cout << "sizeof(int*)      = " << sizeof(int*) << "\n";
    std::cout << "sizeof(double*)   = " << sizeof(double*) << "\n";
    std::cout << "sizeof(char*)     = " << sizeof(char*) << "\n";
    std::cout << "sizeof(void*)     = " << sizeof(void*) << "\n";
    std::cout << "sizeof(int**)     = " << sizeof(int**) << "\n";
    std::cout << "所有指標在同一平台上大小相同。\n";

    return 0;
}

// ── 函式定義 ──────────────────────────────────────

void swapByPtr(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void printValue(const int* ptr) {
    if (ptr != nullptr) {
        std::cout << "  值 = " << *ptr << "(透過 const 指標讀取,不能修改)\n";
    }
}

Artículos relacionados