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

C 語言函數參數傳遞深度解析:陣列、指針與元素傳遞的本質區別

     編輯:關於C語言

前言

函數參數傳遞是 C 語言核心機制之一。本文聚焦於**陣列作為形式參數**時的傳遞語義,對比三種寫法的本質差異,並釐清「陣列名退化為指針」的核心規則,助你避開傳遞陷阱,寫出正確高效的代碼。

核心原則:陣列參數傳遞的是地址

當陣列名作為實參傳遞給函數時,**不會複製整個陣列**,而是將**指向首元素的指針**傳遞給形參。因此:

  • 形參可聲明為 int *n 或 int n[](等價)。
  • 函數內對陣列元素的修改**直接影響原陣列**(引用傳遞語義)。
  • 型別必須嚴格匹配(int 陣列對應 int* 形參)。

三種傳遞方式對比實戰

方式一:傳遞整個陣列(指針/陣列語法)

/* 聲明 */
void disp(int *n);   // 或 void disp(int n[]);

/* 調用 */
int m[10];
for(i=0;i<10;i++) m[i]=i;
disp(m);             // 傳遞首元素地址

/* 定義:指針算術遍歷 */
void disp(int *n) {
    for(j=0;j<10;j++)
        printf("%3d", *(n++));  // n 遞增遍歷
    printf("\n");
}

特點:高效、原始語義、函數可修改原陣列。

方式二:逐個傳遞陣列元素(值傳遞)

/* 聲明 */
void disp(int n);    // 單個 int 形參

/* 調用 */
for(i=0;i<10;i++) {
    m[i]=i;
    disp(m[i]);      // 傳遞第 i 個元素的**值**
}

/* 定義 */
void disp(int n) {
    printf("%3d\t", n);
}

特點:值傳遞,函數內修改 n 不影響原陣列;效率較低(多次函數調用開銷),但語義隔離性好。

方式三:傳遞陣列指針(顯式指針語法)

本質同方式一,僅寫法差異:

void disp(int *n);  // 明確指針類型
disp(m);            // m 隱式轉換為 &m[0]
/* 函數內用 n[j] 或 *(n+j) 訪問 */

關鍵技術細節

  1. 陣列名在表達式中(除 sizeof、&、字符串字面量初始化外)**自動退化為指向首元素的指針**。
  2. 形參聲明等價性:void f(int a[])、void f(int a[10])、void f(int *a) 在函數簽名中**完全等價**,編譯器均視為 int *a。
  3. sizeof 陷阱:函數內對形參 sizeof(a) 返回指針大小(2/4/8 字節),**而非陣列大小**。若需長度,必須額外傳遞 size 參數。
  4. 多維陣列:void f(int a[][COLS]) 或 void f(int (*a)[COLS]),首維退化,次維保留,指針算術按行跨度計算。

最佳實踐建議

場景推薦寫法理由
需修改原陣列、高效遍歷void f(int *a, size_t n)明確指針語義,攜帶長度
僅讀取、不修改void f(const int *a, size_t n)const 防呆,文檔化意圖
需語義隔離、陣列較小逐元素值傳遞或複製陣列避免副作用,代價可控
多維陣列void f(int (*a)[COLS], size_t rows)保留類型信息,指針算術正確

常見錯誤與修正

/* 錯誤:試圖傳遞整個陣列副本 */
void f(int a[10]) { ... }  // 實為指針,非副本
f(arr);                    // 仍傳地址

/* 正確:若真需要副本,手動複製 */
void f(int a[10]) {
    int local[10];
    memcpy(local, a, sizeof(local)); // 需傳長度或固定大小
    ...
}

總結

C 語言函數參數**永遠是值傳遞**,但陣列名在傳遞時退化為首元素指針,形成「模擬引用傳遞」的效果。理解「退化規則」、「形參等價性」、「sizeof 失效」三大核心點,配合 const 與顯式長度參數,即可駕馭各類陣列參數場景,寫出既安全又高效的函數接口。

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