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

C語言函數參數傳遞與返回值機制:值傳遞本質與模擬引用技巧

     編輯:關於C語言

核心鐵律:C 語言只有值傳遞

「C 語言參數傳遞只有值傳遞。」函數調用時,實參的值被拷貝給形參。形參是函數內部的局部變量,修改不影響實參。

一、基本類型傳遞:拷貝即隔離


void modify(int x) {
    x = 20; // 修改形參副本
}

int main() {
    int a = 10;
    modify(a);
    printf("%d\n", a); // 輸出 10,a 未變
    return 0;
}

二、模擬引用傳遞:傳遞地址 (指針)

若需在函數內修改實參,傳遞實參地址,函數通過解引用修改原內存。


void modify(int *px) {
    *px = 20; // 解引用修改原變量
}

int main() {
    int a = 10;
    modify(&a); // 傳遞地址
    printf("%d\n", a); // 輸出 20
    return 0;
}

這是值傳遞指針值,實現了引用語義。標準庫 scanf("%d", &n) 同理。

三、數組傳遞:退化為指針

數組名作為實參時退化為首元素指針,形參接收指針。函數內可修改數組內容。


// 三種等價聲明
void process(int arr[]);
void process(int arr[10]); // 10 被忽略
void process(int *arr);

void process(int *arr) {
    arr[0] = 99; // 修改原數組首元素
    // arr = NULL; // 僅修改局部指針副本,不影響實參
}

int main() {
    int a[5] = {1,2,3,4,5};
    process(a);
    printf("%d\n", a[0]); // 99
    return 0;
}

⚠️ 函數內 sizeof(arr) 返回指針大小,非數組大小。需額外傳遞長度參數。

四、多參數與類型匹配


void foo(int a, double b, char *str); // 聲明

foo(10, 3.14, "hello"); // 調用:實參類型須與形參兼容
// 隱式轉換:int→double, 數組→指針, 字面量→const char*

嚴格匹配參數個數、順序、類型。舊式 K&R 風格已廢棄,必須用原型聲明。

五、返回值機制

1. 基本返回


int square(int x) {
    return x * x; // 返回值拷貝給調用者
}

// 調用
int result = square(5); // result = 25
printf("%d\n", square(5)); // 直接用作表達式

2. 返回指針:生命週期陷阱


// ❌ 錯誤:返回局部變量地址
int* bad() {
    int x = 10;
    return &x; // 棧內存函數返回即失效
}

// ✅ 正確:返回靜態/全局/堆內存地址
int* good_static() {
    static int x = 10;
    return &x; // 靜態存儲區,生命週期全程
}

int* good_heap() {
    return malloc(sizeof(int)); // 調用者負責 free
}

3. 返回結構體 (C99)


struct Point { int x, y; };

struct Point make_point(int x, int y) {
    return (struct Point){x, y}; // 復合字面量,返回值拷貝
}

4. 多返回值模式

六、const 正確性:防止誤修改


// 承諾不修改指向的數據
void print_arr(const int *arr, int n) {
    // arr[0] = 1; // 編譯錯誤
    for (int i=0; i

七、變長參數:stdarg.h


#include 

double average(int count, ...) {
    va_list ap;
    va_start(ap, count);
    double sum = 0;
    for (int i = 0; i < count; i++)
        sum += va_arg(ap, double);
    va_end(ap);
    return sum / count;
}

// 調用
printf("%.2f\n", average(3, 1.0, 2.0, 3.0)); // 2.00

八、最佳實踐清單

  • ✅ 只讀參數加 const (指針/數組)。
  • ✅ 需修改實參 → 傳遞地址 (int*)。
  • ✅ 數組參數 → void func(int *arr, size_t n),顯式傳長度。
  • ✅ 返回結構體替代多輸出參數 (小結構體)。
  • ✅ 動態分配內存返回 → 文檔註明調用者 free。
  • ❌ 返回局部變量/數組地址。
  • ❌ 形參名與實參名同名以為共享內存。
  • ❌ 忽略 sizeof(數組參數) 退化為指針大小。

總結

C 語言堅持值傳遞:標量拷貝值,指針拷貝地址,數組退化為指針。理解「拷貝什麼、修改什麼、生命週期誰負責」,是編寫正確、高效、安全函數接口的關鍵。善用 const、輸出參數、結構體返回,構建清晰契約的 API。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
模式示例優點缺點
輸出參數 (指針)void divmod(int a, int b, int *q, int *r)標準、高效調用繁瑣
返回結構體struct DivMod { int q, r; };清晰、類型安全拷貝開銷 (小結構可忽略)
全局/靜態緩衝區char *strtok(...)簡單非線程安全、可重入性差