早前周星星大哥發文「用數組引用避免數組降階」,當時未深悟。如今重讀,結合四大核心問題逐層剖析,終得真諦。本文從形參實參關係、數組名指針關係、引用本質、聲明表達式解析四維入手,徹底講透數組形參傳遞機制。
void Foo(int a); Foo(10); 實參 10 傳給形參 a,本質是 賦值過程(a=10)。所有類型同理,可在 VC 中調試驗證。
C 標準規定:表達式中數組名轉換為指向首元素的指針;函數參數聲明中數組名調整為指針。因此:
void Foo1(int arr[100]) {}
void Foo2(int arr[]) {}
void Foo3(int *arr) {}
// 三者完全等效
但聲明處不同:int a[100]; int *b; — sizeof(a)=400,sizeof(b)=4。數組名在 sizeof 中不轉換,保留完整類型信息。
引用一經定義即綁定目標,對引用的任何操作直接反映在被引用變量上,不像指針只是訪問方式。驗證代碼:
int a=10; int &a_ref=a; int b=20; int &b_ref=b;
a_ref = b_ref; // 實為 b 賦值給 a,a_ref 仍綁定 a
cout << a_ref << " " << b_ref; // 20 20
cout << a << " " << b; // 20 20
int *p=&a, *q=&a_ref; // p==q,取引用地址得被引用變量地址
// 指針可改指向:p=&a; q=&b; p=q; // p,q 同指 b,a 不變
運行結果證明:引用「惡鬼附體」,指針「可換目標」。
分析 int (&arr)[100]:
arr&arr → 引用(&arr)[100] → 100 元素數組int → 元素類型arr 是「含 100 個 int 的數組的引用」用 typedef 化繁為簡:typedef int INTARR[100]; void Foo(INTARR &arr) {} 瞬間明瞭。
int a[100];
int *pa = a;
int (&a_ref)[100] = a;
sizeof(a) // 400,數組完整類型
sizeof(pa) // 4,指針大小
sizeof(a_ref) // 400,引用即數組本體
函數傳遞即賦值:
Foo1(a) → 形參 int arr[100] 調整為 int*,實際傳 &a[0],sizeof(arr)=4。
Foo2(a) → 形參 int (&arr)[100],引用綁定數組,sizeof(arr)=400。
並非函數把數組「降階」,而是聲明機制決定:指針形參丟失長度,引用形參保留長度。
main(int argc, char** argv),防溢出,安全性高。'\0' 結尾,無長度限制(變量長度受類型限制,如 unsigned byte 限 256)。a[3][3] = {{...}, {...}, {-1,-1,-1}},遇全 -1 行知結束。方法靈活多變,關鍵在人。丹尼斯·里奇曾言:「C 詭異離奇,缺陷重重,卻獲得巨大成功。」