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

C 語言函式進階:回傳值機制、函式宣告風格、陣列參數與遞迴完整解析

     編輯:關於C語言

函式是 C 語言模組化的基本單元。本文深入剖析 return 回傳值機制、傳統 vs 現代函式宣告風格、陣列作為參數的退化規則、遞迴函式設計模式,並提供標準庫級錯誤處理範例。

函式回傳值機制

return 語句語義

return 表達式;      // 計算表達式值,複製至呼叫端暫存器/棧框
return (表達式);    // 等價,括號可加可不加
return;             // 僅用於 void 函式,直接返回控制權
  • 函式最多執行一個 return(控制流離開函式)。
  • 回傳型別與函式定義型別不符時,隱含轉型(如 double→int 截斷)。
  • void 函式不可用於運算式中(x = f(); 編譯錯誤)。

型別一致性建議

// 錯誤:定義 double 卻 return int
double bad() { return 3; }  // 隱含轉 3.0,但誤導維護者

// 正確:明確回傳型別
double good() { return 3.0; }

函式宣告:傳統 vs 現代(ANSI C)

風格語法參數檢查適用場景
傳統 (K&R)int max();無(呼叫端隨意傳參)舊碼維護
現代 (ANSI)int max(int a, int b);完整型別/個數檢查所有新專案
現代簡化int max(int, int);型別檢查,參數名可省略標頭檔常用

強制要求:C99 起禁止隱含函式宣告(呼叫前必須可見宣告或定義)。

可省略宣告的四種情況

  1. 回傳 int/char 且未出現參數型別轉換需求(舊式隱含 int 規則,現代不建議依賴)。
  2. 被呼叫函式定義在呼叫者之前(定義即宣告)。
  3. 檔案最上方集中宣告所有函式原型(專案規範常見)。
  4. 標準庫函式:#include <header.h> 已含宣告。

陣列作為函式參數:退化為指標

兩種傳遞模式

模式語法實際傳遞函式內可修改原陣列?
單一元素f(arr[i])值傳遞 int否
整個陣列f(arr)指標 int*(首元素位址)是

陣列參數三種等價寫法


void f1(int arr[]);      // 建議:語意清楚
void f2(int arr[10]);    // 長度被忽視,僅文件用
void f3(int *arr);       // 本質:指標

函式無法得知陣列長度,必須額外傳遞 size_t n。

範例:正數歸零過濾器


void print_nonneg(int val) {
    printf("%d ", val > 0 ? val : 0);
}
int main() {
    int a[5];
    for (int i=0; i<5; ++i) scanf("%d", &a[i]);
    for (int i=0; i<5; ++i) print_nonneg(a[i]);  // 元素傳值
}

二維陣列參數:必須指定列寬


void print_mat(int mat[][4], int rows) {  // 或 int (*mat)[4]
    for (int i=0; i

遞迴函式設計模式

三要素

  1. 基底情況:直接回傳結果,終止遞迴。
  2. 遞迴步驟:將問題縮小,呼叫自身。
  3. 狀態縮減:參數朝基底情況收斂,保證終止。

經典範例:階乘


long long fact(int n) {
    if (n <= 1) return 1;          // 基底
    return n * fact(n - 1);        // 遞迴步驟 + 縮減
}

尾端遞迴優化(TCO)


// 非尾端:乘法在遞迴返回後
long long fact(int n) { return n<=1?1:n*fact(n-1); }

// 尾端:累積器帶入參數
long long fact_tail(int n, long long acc) {
    if (n <= 1) return acc;
    return fact_tail(n-1, n*acc);  // 最後動作是呼叫自身
}
// GCC -O2 可優化為迴圈,避免棧溢位

變數引數函式(stdarg.h)


#include 
double average(int count, ...) {
    va_list ap;
    va_start(ap, count);
    double sum = 0;
    for (int i=0; i

函式指標與回調


int cmp_int(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}
qsort(arr, n, sizeof(int), cmp_int);  // 標準庫回調

最佳實務檢查清單

  1. 所有函式在標頭檔以現代原型宣告。
  2. 陣列參數伴隨 size_t len。
  3. const 修飾唯讀指標參數(void f(const int *p))。
  4. 遞迴深度 < 1000 且無 TCO 時改寫迭代。
  5. 錯誤碼回傳 vs errno 統一專案規範。
  6. 函式指標型別用 typedef 簡化(typedef int (*CmpFn)(const void*,const void*);)。

函式設計遵循「單一職責、介面最小化、錯誤可檢測」,是構建可維護 C 專案的基石。

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