現象
兩張圖片程式碼差異在於函數前向宣告:
- 圖一:`int max();`(無參數) → 編譯警告/錯誤或執行異常。
- 圖二:`int max(struct Student *);`(帶參數) → 正常執行。
核心原因:K&R 舊式宣告 vs ANSI C 原型
C 標準演進:
- K&R C (舊式):`int max();` 表示「接受未指定數量/類型參數的函數」,編譯器不檢查呼叫端參數,直接依呼叫慣例傳遞,極易造成堆疊錯誤。
- ANSI C (C89 起):`int max(struct Student *);` 為函數原型,編譯器會檢查呼叫端參數類型、數量,並自動進行必要的型別轉換(如 `float` → `double`、陣列退化為指標)。
為何圖二正常?
原型宣告讓編譯器知道 `max` 接受單一指標參數,呼叫端傳遞 `struct Student *` 時型別匹配,參數壓棧正確,函數內部存取成員無誤。
最佳實務
「所有函數在使用前必須提供完整原型宣告(含參數類型),建議統一放在標頭檔 (.h) 供多檔案包含。」
- 避免隱式宣告(C99 起已移除隱式 `int` 回傳)。
- 啟用編譯器警告:`-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes`。
- 若函數無參數,寫 `void`:`int max(void);`。
補充:標頭檔範例
// max.h
#ifndef MAX_H
#define MAX_H
struct Student { char name[20]; int score; };
int max(struct Student *stu, int n); // 完整原型
#endif