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

C 語言指針進階十大鐵律:從內存模型到函數指針的完整知識體系

     編輯:C 語言入門

鐵律 1:指針是一種數據類型

  • 指針變量佔用內存(32位 4B,64位 8B),存儲地址值。
  • *p 兩層含義:聲明時標識指針類型;使用時解引用操作目標內存。
  • 指針變量與其指向的內存塊是兩個獨立實體。
  • 指針類型決定步長:p++ ≡ (char*)p + sizeof(*p)。

鐵律 2:*p 是指針存在的最大意義 —— 間接賦值

三個必要條件:

  1. 兩個變量(實參 + 形參)。
  2. 建立關聯:形參 = &實參。
  3. 在被調函數中 *形參 = 新值 間接修改實參。

推論:n 級指針形參可間接修改 n-1 級指針實參。這是 C 語言模擬「引用傳遞」的核心機制。

鐵律 3:理解指針必須結合內存四區模型

  • 主調函數可將堆、棧、全局區地址傳給被調函數。
  • 被調函數只能返回堆或全局區地址,返回棧區地址導致野指針。
  • 指針參數具有輸入/輸出雙重屬性,需明確誰分配誰釋放。

鐵律 4:指針應用必須結合函數調用模型

十大典型接口模式:

級別/方向典型場景內存分配方例子
一級輸入只讀緩衝區/數組主調分配(棧/堆)show(buf), showArray(arr, len)
一級輸出返回長度/狀態碼主調分配,被調寫入getLen(file, &len)
二級輸入字符串數組/二維數組主調分配main(argc, argv), showMatrix(mat, rows)
二級輸出動態分配結構體/數組被調分配堆,主調負責釋放getTeacher(&p), getData(&buf, &len)
三級輸出多行文本/多維數組被調分配堆,提供釋放函數getFileAllLine(&lines, &cnt)

鐵律 5:一級指針輸入 —— 只讀與遍歷

void showArray(int *arr, int n) { for(int i=0;i

主調在棧/堆分配,被調僅讀取,const 修飾增強可讀性。

鐵律 6:二級指針輸出 —— 動態構建數組/結構體

int getTeacher(Teacher **pp) {
    *pp = malloc(sizeof(Teacher));
    (*pp)->name = malloc(100);
    return 0;
}
void freeTeacher(Teacher **pp) { free((*pp)->name); free(*pp); *pp = NULL; }
  • 被調分配堆內存,通過 *pp 回傳地址。
  • 提供配套釋放函數,參數用 void** 可置空實參,防野指針。

鐵律 7:三級指針輸出 —— 多層動態結構

int getFileAllLine(char ***content, int *lineCnt) {
    *content = malloc((*lineCnt+1) * sizeof(char*));
    for(int i=0;i<*lineCnt;i++) (*content)[i] = malloc(MAX_LINE);
    return 0;
}

鐵律 8:野指針防禦三部曲

  1. 定義即初始化 NULL。
  2. free 前判空,free 後置 NULL。
  3. 輸出型接口提供 Free(void**) 統一釋放並置空。

鐵律 9:一般業務代碼禁用裸 malloc/free/new/delete

封裝為模塊內部實現,對外提供 Create/Destroy 或 Get/Free 對,統一內存策略,便於檢測洩漏、池化、統計。

鐵律 10:函數指針是 C 語言實現多態與回調的基石

typedef int (*Handler)(void *ctx, int cmd, void *data);
// 註冊回調
void registerHandler(Handler h) { g_handler = h; }
// 面向對象雛形
struct VTable { void (*init)(void*); void (*process)(void*); };
struct Object { struct VTable *vptr; void *priv; };

函數指針讓 C 具備「行為參數化」能力,是框架設計、驅動開發、狀態機實現的核心工具。


附錄:字符串與結構體指針實戰模式

字符串函數接口規範

  • 主調分配目標緩衝區,傳入指針與容量,被調寫入並返回實際長度。
  • 被調分配情況:返回 char*,文檔註明調用方負責 free,或提供 FreeStr(char**)。

結構體淺拷貝 vs 深拷貝

// 編譯器默認淺拷貝:指針成員僅複製地址
// 深拷貝手動實現:
void deepCopy(Teacher *dst, Teacher *src) {
    memcpy(dst, src, sizeof(Teacher));
    dst->name = malloc(strlen(src->name)+1);
    strcpy(dst->name, src->name);
}

柔性數組成員

struct Packet { int len; char data[]; }; // C99
struct Packet *p = malloc(sizeof(struct Packet) + 100);
p->len = 100; // data 緊隨結構體,單次分配

總結

指針是 C 語言的靈魂。掌握內存四區、函數調用棧幀、間接賦值三條件、輸入輸出語義、野指針防禦、函數指針回調這六大支柱,即可駕馭 90% 的 C 工程難題。記住:畫圖驗證、邊界測試、所有權清晰是寫出健壯指針代碼的鐵律。

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