函數是 C 語言模組化的基本單位。理解函數調用機制——參數如何傳遞、返回值如何處理、堆疊如何變化——是寫出正確、高效代碼的基石。本文以 Turbo C 2.0 為環境,詳細拆解簡單調用全流程。
Turbo C 採用呼叫者清理堆疊的 cdecl 呼叫慣例:
CALL 指令跳轉至被呼叫函數BP、分配區域變數空間)AX/DX:AX 返回值(整數/指標用 AX,長整數用 DX:AX)RET 返回#include <stdio.h>
#include <conio.h>
int maximum(int x, int y, int z); // 函數原型宣告
int main(void) {
int i, j, k;
printf("i, j, k = ?\n");
scanf("%4d%4d%4d", &i, &j, &k);
maximum(i, j, k); // 呼叫函數,忽略返回值(教學範例疏漏)
getch();
return 0;
}
int maximum(int x, int y, int z) {
int max = (x > y) ? x : y;
max = (max > z) ? max : z;
printf("The maximum value of the 3 data is %d\n", max);
return max; // 良好習慣:返回計算結果供呼叫者使用
}
int 返回、參數不檢查,極易導致堆疊破壞C 語言唯一支援按值呼叫。實參值被複製給形參,函數內修改形參不影響實參。
void swap(int a, int b) {
int t = a; a = b; b = t; // 僅交換區域副本
}
int main() {
int x=1, y=2;
swap(x, y); // x,y 不變
}
需交換實際變數時,必須傳遞指標:
void swap(int *a, int *b) {
int t = *a; *a = *b; *b = t;
}
swap(&x, &y); // 正確交換
void 函數無返回值void 函數所有路徑必須返回值(C99 強制)printf、scanf、strlen 等標準庫函數遵循相同調用慣例,差別在於:
stdio.h、string.h).lib,連結時自動解析| 錯誤 | 後果 | 修正 |
|---|---|---|
| 缺少函數原型 | 參數型別不匹配導致堆疊錯誤 | 在檔案頂部或頭檔宣告原型 |
| 實參/形參個數不符 | 堆疊不平衡,程式崩潰 | 嚴格對應宣告與呼叫 |
| 忘記返回值 | 返回垃圾值,邏輯錯誤 | 所有路徑覆蓋 return |
| 指標參數未解參考 | 修改區域指標副本 | 函數內使用 *ptr 存取實際資料 |
函數名稱本質是函數入口地址,可賦值給函數指標變數:
int (*funcPtr)(int, int) = maximum; // 指向 maximum
int result = funcPtr(3, 5); // 透過指標調用
這是實現回調、狀態機、插件架構的基礎。
函數調用看似簡單,實則涉及堆疊幀建立、參數壓棧、暫存器保存/恢復、返回值傳遞等底層機制。掌握「按值呼叫、原型宣告、返回值規範」三大核心,並善用指標突破單向傳值限制,是 C 語言模組化程式設計的入門鑰匙。