首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

C/C++ 指針入門完全指南:從內存地址到動態分配、函數傳遞與智能指針現代化

     編輯:VC++

什麼是指針?

指針** 是一個變量,其值是**另一個變量的內存地址**。它不直接存儲數據,而是「指向」數據所在的位置。這是 C/C++ 手動內存管理、高效數據結構、系統編程的基石。

基礎語法與核心操作

操作符號語義範例
聲明`*`類型修飾符,`int* p` = 指向 int 的指針`int* p;`
取地址`&`獲取變量內存地址`p = #`
解引用`*`訪問指針指向的值`*p = 20;`
指針算術`++` `--` `+` `-`按類型大小移動 (指向下一個/上一個元素)`p++` 移動 `sizeof(int)` 字節

最小化範例


#include 

int main() {
    int num = 10;
    int* p = #      // p 存儲 num 的地址
    printf("num 值: %d\n", num);        // 10
    printf("p 地址: %p\n", (void*)p);   // 如 0x7ffe...
    printf("*p 值: %d\n", *p);          // 10 (解引用)
    
    *p = 25;              // 通過指針修改 num
    printf("num 新值: %d\n", num);      // 25
    return 0;
}

經典陷阱:返回局部變量地址


// ❌ 錯誤:棧上局部變量函數結束即銷毀
int* BadFunction() {
    int local = 42;
    return &local; // 返回已釋放棧內存地址 → 未定義行為
}

// ✅ 正確:動態分配 (堆內存) 或靜態/全局變量
int* GoodFunction() {
    int* p = (int*)malloc(sizeof(int)); // C 風格
    *p = 42;
    return p; // 調用者負責 free()
}

// C++ 現代風格:智能指針自動管理
#include 
std::unique_ptr ModernFunction() {
    return std::make_unique(42); // 自動釋放,無內存洩漏
}

動態內存分配

語言分配釋放備註
C`malloc` / `calloc` / `realloc``free`不調用構造/析構,**不適用於 C++ 類對象**
C++`new Type` / `new Type[N]``delete` / `delete[]`調用構造函數/析構函數,**必須配對使用**
C++11+`std::make_unique` / `std::make_shared`**自動** (RAII)**首選**,零裸指針,異常安全

數組分配與釋放


// C
int* arr = (int*)malloc(10 * sizeof(int));
free(arr);

// C++
int* arr = new int[10];
delete[] arr; // 必須用 delete[],否則僅析構第一個元素 → 內存洩漏/UB

// 現代 C++:容器替代裸數組
std::vector vec(10); // 自動管理,擴容、邊界檢查、RAII
std::array arr; // 固定大小,棧分配,零開銷

指針作為函數參數:傳遞地址實現「引用語義」


// C 風格:修改調用者變量
void AddFive(int* n) {
    *n += 5; // 解引用修改
}
int main() {
    int val = 10;
    AddFive(&val); // 傳遞地址
    printf("%d", val); // 15
}

// C++ 引用參數 (語法糖,本質仍是指針)
void AddFiveRef(int& n) { n += 5; }
AddFiveRef(val); // 無需 &,調用處更清晰

// 現代 C++:傳值 + 返回值 (函數式風格) 或 span/view
int AddFivePure(int n) { return n + 5; }
std::span Process(std::span data) { ... } // 非擁有視圖

指向類/結構的指針:成員訪問運算符 `->`


struct Node { int value; Node* next; };

Node* head = new Node{1, nullptr};
head->value = 10;        // 等價於 (*head).value
head->next = new Node{2, nullptr};

// 現代 C++:智能指針鏈表
struct SmartNode {
    int value;
    std::unique_ptr next; // 擁有權語義清晰
};
auto head = std::make_unique(SmartNode{1, nullptr});
head->next = std::make_unique(SmartNode{2, nullptr});
// 無需手動 delete,離開作用域自動遞歸釋放

指向數組的指針與指針算術


int arr[3] = {10, 20, 30};
int* p = arr;        // 數組名退化為首元素地址
// 等價:int* p = &arr[0];

printf("%d\n", *p);   // 10
p++;                  // 移動到下一個 int
printf("%d\n", *p);   // 20
printf("%d\n", *(p+1)); // 30 (不修改 p)

// 關鍵:編譯器不檢查越界,程序員自負
// 現代替代:std::span view(arr, 3); // 帶邊界信息的視圖

多級指針與指針數組


// 指針的指針:修改指針本身 (如鏈表頭插入)
void InsertHead(Node** head, int val) {
    Node* newNode = new Node{val, *head};
    *head = newNode; // 修改調用者的 head 指針
}

// 指針數組:字符串數組、argv
char* names[] = {"Alice", "Bob", "Charlie"};
// 等價:char** names = ... (指向指針的指針)

const 與指針:四種組合語義

聲明含義可修改指針?可修改值?
`int* p`指向 int 的指針✅✅
`const int* p` / `int const* p`指向**常量 int** 的指針✅❌
`int* const p`**常量指針** 指向 int❌✅
`const int* const p`常量指針指向常量 int❌❌

口訣:**`const` 在 `*` 左 → 值不可變;`const` 在 `*` 右 → 指針不可變。**

現代 C++:智能指針與 RAII — 徹底告別裸指針


#include 

// 獨占所有權:不可複製,可移動
std::unique_ptr p1 = std::make_unique();
auto p2 = std::move(p1); // 所有權轉移,p1 變空

// 共享所有權:引用計數,線程安全控制塊
std::shared_ptr sp1 = std::make_shared();
std::shared_ptr sp2 = sp1; // 計數+1
// 離開作用域計數-1,歸零時自動 delete

// 弱引用:打破循環引用
std::weak_ptr wp = sp1;
if (auto locked = wp.lock()) { /* 安全訪問 */ }

// 自定義刪除器:管理非 new 分配資源 (FILE*, socket, GPU buffer)
auto file = std::unique_ptr(fopen("a.txt","w"), fclose);

常見錯誤與調試技巧

錯誤現象排查工具
野指針 (未初始化)隨機崩潰/數據損壞編譯器警告 `-Wall`、AddressSanitizer (`-fsanitize=address`)
懸空指針 (use-after-free)訪問已釋放內存ASan、Valgrind、智能指針消除
內存洩漏 (忘記 delete)內存單調增長、OOMValgrind、Visual Studio 診斷工具、智能指針
雙重釋放堆損壞、崩潰ASan、所有權語義清晰化
緩衝區溢出覆蓋相鄰內存、安全漏洞ASan、MSVC `/GS`、std::span/容器

C 與 C++ 關鍵差異總結

  • C:`malloc`/`free`、無構造析構、手動管理、易出錯。
  • C++:`new`/`delete` 調用構造/析構、**RAII (資源獲取即初始化)**、**智能指針 (`unique_ptr`/`shared_ptr`) 是現代標準**、容器/算法/視圖替代裸指針算術。
  • **原則**:現代 C++ 代碼中 **99% 場景不應出現裸指針 (`T*`)**,僅在與 C API 交互、非擁有觀察者 (`T*`/`std::span`/`std::string_view`)、性能極致熱路徑時使用。

結語

指針是 C/C++ 操控內存的核心工具,理解**地址、解引用、所有權、生命週期**是寫出正確高效代碼的前提。**現代 C++ 以 RAII 與智能指針將內存管理自動化、異常安全化、所有權語義化**,應作為首選範式。掌握裸指針機制是為了讀懂舊代碼、調試底層問題、與 C 互操作,而非日常開發工具。

  1. 上一篇文章: No
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved