「數組作為函數參數退化為指針」是 C 語言核心機制:函數接收的只是數組首元素地址,所有長度信息丟失。這導致函數內 `sizeof(arr)` 返回指針大小 (4/8 字節) 而非數組總大小。
退化演示
void func(int arr[]) { // 等價於 int *arr
printf("函數內 sizeof(arr) = %zu\n", sizeof(arr)); // 8 (64位指針大小)
printf("元素個數? 無法直接獲取!\n");
}
int main() {
int a[10] = {1,2,3,4,5,6,7,8,9,10};
printf("主函數 sizeof(a) = %zu\n", sizeof(a)); // 40 (10 * 4)
func(a); // 傳遞 &a[0]
}
三種在函數內獲取長度的方案
| 方案 | 適用場景 | 示例 |
| 額外傳長度參數 | 通用、零開銷 | `void func(int *arr, size_t len)` |
| 約定結束標記 | 字符串、特定數據 | `int a[] = {1,2,3, -1};` 以 -1 結束 |
| 結構體封裝 | 現代 C 風格 | `typedef struct { int *data; size_t len; } Array;` |
指針 vs 數組:核心區別
| 特性 | 數組 `int a[10]` | 指針 `int *p` |
| 內存分配 | 棧上連續 40 字節 | 僅 8 字節變量,指向任意地址 |
| `sizeof` | 總大小 (40) | 指針大小 (8) |
| 可修改指向 | ❌ `a = p` 編譯錯誤 | ✅ `p = a` 合法 |
| 地址值 | `&a` 類型 `int(*)[10]` | `&p` 類型 `int**` |
| 作為參數 | 退化為指針 | 本身即指針 |
經典面試題
void test(char str[100]) {} // 參數仍退化為 char *str
// 編譯器完全忽略 [100],無任何約束作用
記住:只有在數組定義的作用域內,`sizeof` 才能得到完整大小。跨函數傳遞必須額外攜帶長度。