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

C語言函數完全指南:定義調用、參數傳遞三大模式、遞歸與庫函數實戰

     編輯:關於C語言

函數:C語言模塊化編程的核心構建塊

函數是 C 程序的基本模塊單元,所有計算任務最終都由函數執行。本文系統梳理函數定義語法、三種參數傳遞機制(值傳遞/地址傳遞/引用傳遞)、遞歸思想、標準庫常用函數及實戰避坑指南,助你構建清晰、可復用、高性能的代碼架構。

一、 函數定義與聲明規範

// 完整函數定義
返回類型 函數名(參數列表) {
    // 函數體
    return 表達式; // 無返回值用 void
}

// 聲明(原型):通常放在頭文件 .h 中
返回類型 函數名(參數類型列表); // 參數名可省略

// 示例:計算兩數之和
int add(int x, int y) {
    return x + y;
}

// 調用
int result = add(3, 5); // 實參 3, 5 傳遞給形參 x, y

關鍵規則:

  • C 不支持函數嵌套定義(GNU 擴展除外)。
  • 函數調用開銷:棧幀分配、參數壓棲、跳轉、返回、棧幀銷毀。內聯函數 (inline/static inline) 可消除開銷,適合短小高頻函數。

二、 參數傳遞三大模式深度對比

這是面試必考、Bug 高發核心區,必須徹底理解內存與語義差異。

1. 值傳遞 —— 默認機制,傳遞副本

void swap_val(int x, int y) {
    int tmp = x; x = y; y = tmp; // 僅修改局部副本
}
int a=4, b=6;
swap_val(a, b); // a,b 不變!
  • 本質:實參值拷貝給形參(int x = a;),函數內操作獨立內存。
  • 優點:安全,不影響原數據。
  • 缺點:大結構體拷貝開銷大;無法修改實參。

2. 地址傳遞 —— 傳遞指針,間接修改

void swap_ptr(int *px, int *py) {
    int tmp = *px; *px = *py; *py = tmp; // 解引用修改實參內存
}
int a=4, b=6;
swap_ptr(&a, &b); // a=6, b=4 成功交換!
  • 本質:傳遞地址值(int *px = &a;),通過解引用 *px 訪問實參內存。
  • 通用性:C 語言唯一實現「輸出參數」的標準方式,適用於所有類型(含結構體、數組)。

3. 引用傳遞 —— C++ 專屬,C 語言不支持

// 僅 C++ 有效
void swap_ref(int &x, int &y) { // 形參是實參的別名
    int tmp = x; x = y; y = tmp;
}
int a=4, b=6;
swap_ref(a, b); // 調用語法同值傳遞,效果同地址傳遞

注意:C 語言沒有引用類型,請勿混淆。C 中模擬引用語義只能用指針。

三、 遞歸函數:以退為進的藝術

// 階乘:n! = n * (n-1)!
unsigned long long factorial(int n) {
    if (n <= 1) return 1;          // 基線條件
    return n * factorial(n - 1);   // 遞歸步驟
}

// 斐波那契(教學用,實際用迭代/矩陣快速冪)
int fib(int n) {
    if (n <= 1) return n;
    return fib(n-1) + fib(n-2);    // 指數級複雜度,僅示意
}

遞歸三要素:基線條件、遞歸調用、問題規模遞減。棧溢出風險:深度遞歸耗盡棧空間,尾遞歸優化 (TCO) 依賴編譯器支持(GCC -O2 可優化)。

四、 標準庫高頻函數速查

頭文件函數功能關鍵點
string.hstrcpy(dst, src)字符串拷貝目標空間需足夠,無長度檢查(不安全)
strlen(str)字符串長度不含 \0,O(n) 掃描
strstr(haystack, needle)子串查找返回首次出現地址,未找到返回 NULL
stdlib.hatoi(str)字符串轉整數無錯誤檢測,推薦 strtol
stdio.hscanf/fscanf/sscanf格式化輸入返回成功匹配項數,需檢查返回值
printf/fprintf/sprintf格式化輸出格式字符串漏洞風險,用戶輸入不可作格式串

五、 實戰避坑與最佳實踐

  1. 數組傳參退化:void f(int arr[]) 等價 void f(int *arr),sizeof(arr) 失效,必須額外傳長度。
  2. const 修飾指針參數:void print(const int *arr, int n) 承諾不修改內容,編譯器強制檢查,提升接口安全性。
  3. 避免返回局部指針/引用:函數結束棧幀銷毀,返回地址變懸空指針。改用靜態變量、動態分配或輸出參數。
  4. 可變參數:stdarg.h (va_list, va_start, va_arg, va_end) 實現 printf 風格函數,類型安全由程序員保證。
  5. 內聯函數:static inline int max(int a, int b) { return a>b?a:b; } 放頭文件,消除調用開銷,避免函數體過大導致指令緩存失效。

總結:函數是管理複雜度的利器。掌握值/地址傳遞語義差異、善用const、理解棧幀生命週期、熟練標準庫,編寫出「高內聚、低耦合、無副作用」的純函數風格代碼,是 C 語言工程化的關鍵一步。

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