函數與指標的結合運用是C語言威力的核心體現。本文從程式堆疊與堆積記憶體模型出發,深入剖析指標參數傳遞機制、函數指標聲明與應用、回調函數模式、動態記憶體管理陷阱等核心主題,建立系統性認知框架。
現代作業系統為每個執行緒分配獨立程式堆疊,通常位於使用者空間高位址向低位址增長;堆積位於低位址向高位址增長,兩者共享虛擬記憶體空間。
高位址 +------------------+ | 呼叫者區域 | ← 呼叫者保存的暫存器、參數等 +------------------+ | 返回位址 | ← CALL 指令壓入 +------------------+ | 舊基址指標 (EBP/RBP) | ← 建立新堆疊幀 +------------------+ ← 基址指標 (EBP/RBP) 指向此處 | 區域變數 | ← 負位移存取 | ... | +------------------+ | 暫存器溢出區 | ← 編譯器溢出暫存器 +------------------+ | 參數區域 | ← 正位移存取 (呼叫慣例相關) +------------------+ 低位址
push rbp; mov rbp, rsp; sub rsp, N 建立堆疊幀rbp ± offset 存取區域變數/參數mov rsp, rbp; pop rbp; ret 恢復堆疊、彈出返回位址跳轉void swap(int *a, int *b) {
int tmp = *a; *a = *b; *b = tmp;
}
int x=1, y=2; swap(&x, &y); // x=2, y=1
struct BigData { double matrix[100][100]; };
void process(const struct BigData *data); // 僅傳 8 位元組指標,避免複製 80KB
bool parse_int(const char *str, int *out_value); // 回傳成功與否,結果經由 out_value 輸出
void allocate(int **ptr, size_t n) {
*ptr = malloc(n * sizeof(int)); // 修改呼叫端的指標變數
}
int *p = NULL; allocate(&p, 10); // p 現在指向新記憶體
int* dangerous() {
int local = 42;
return &local; // 錯誤!堆疊記憶體函數返回即失效
}
int* safe_static() {
static int value = 42; // 靜態儲存期,生命週期 = 程式執行期
return &value;
}
int* safe_heap() {
return malloc(sizeof(int)); // 堆積記憶體,呼叫者負責 free()
}
if (ptr == NULL)free(ptr) 後立即 ptr = NULLfree 非 malloc 記憶體、重複 free、free 野指標if ((p = malloc(n)) == NULL) handle_error();// 基本形式:回傳型別 (*指標名稱)(參數列表) int (*func_ptr)(int, int); // 指向接受兩個 int、回傳 int 的函數 // 使用 typedef 簡化 typedef int (*BinaryOp)(int, int); BinaryOp op = add; // 函數名自動轉換為位址
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
BinaryOp ops[] = {add, mul, NULL}; // 函數指標陣列
int result = ops[0](3, 4); // 7,透過指標呼叫
// qsort 標準庫簽名
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
// 使用範例
int cmp_int(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int arr[] = {5,2,8,1,9};
qsort(arr, 5, sizeof(int), cmp_int);
void* 不可儲存函數指標 (標準未保證大小相容)== != 比較BinaryOp create_op(char op_char); 工廠模式void* context 實現閉包效果typedef struct {
void (*on_data)(void *ctx, const char *data, size_t len);
void (*on_error)(void *ctx, int code);
void *context;
} EventHandler;
void process_stream(FILE *fp, const EventHandler *handler) {
char buf[4096];
size_t n;
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
handler->on_data(handler->context, buf, n);
}
if (ferror(fp)) handler->on_error(handler->context, errno);
}
掌握堆疊幀機制、指標參數語義、函數指標運用,能讓你寫出模組化、可擴充、高效能的 C 程式。建議配合 GDB 觀察實際堆疊佈局、閱讀 glibc/qsort 等標準庫實作、實作簡易事件循環框架深化理解。