習慣了 Java int[] arr 或 C# int[] arr 的開發者,初次接觸 C/C++ 數組時常會困惑:為什麼數組名有時是指標、有時又不是?為什麼 int* a = {1,2} 編譯報錯?本文系統梳理數組聲明、參數傳遞、初始化與 sizeof 的核心規則。
[cpp]
int FindMax1(int* Array); // 寫法 1:顯式指標
int FindMax2(int Array[]); // 寫法 2:數組語法糖
結論:在函數參數列表中,int Array[] 會被編譯器自動轉換為 int* Array。兩者語義完全等價,都是傳遞首元素地址,**數組長度信息丟失**,函數內無法通過 sizeof 獲取元素個數。
[cpp]
// 錯誤:指標無法直接用列表初始化
int* Array1 = {0, 1, 2, 3}; // 編譯失敗
// 正確:數組定義可用列表初始化
int Array2[] = {0, 1, 2, 3}; // 編譯通過,長度自動推導為 4
核心區別:
int* p:聲明一個指標變量,需單獨分配內存(malloc/new)或指向現有對象。int a[]:聲明一個數組對象,編譯器自動分配連續內存,大小由初始化列表或显式長度決定。[cpp]
int a1[10] = {0}; // 全部置 0,C 標準保證未列出元素零初始化
char a2[] = {'a','b','c',0};// 未指定長度,由列表元素數決定(此處為 4)
int a3[8] = {1,2,3,4}; // 長度 8,前 4 個顯式初始化,後 4 個自動補 0
// 等價於 int a3[8] = {1,2,3,4,0,0,0,0};
效率提示:使用 int a[] = {...} 列表初始化比逐元素賦值更高效,編譯器可生成批量內存初始化指令。
[cpp]
int* p = malloc(10 * sizeof(int));
int arr[10] = {0};
sizeof(p); // 4 (32位) 或 8 (64位) —— 指標變量本身的大小
sizeof(arr); // 40 —— 數組佔用的總字節數 (10 * sizeof(int))
口訣:sizeof(數組名) 只有在**數組定義的作用域內**才代表整個數組大小;一旦作為參數傳遞或賦值給指標,即退化為指標,sizeof 返回指標大小。
| 場景 | 語法 | 語義 | 關鍵點 |
|---|---|---|---|
| 函數參數 | int* a / int a[] | 指向首元素的指標 | 長度信息丟失,需額外傳遞 size |
| 定義+初始化 | int a[] = {...} | 數組對象,自動推導長度 | 推薦寫法,高效且安全 |
| 定義+指定長度 | int a[N] = {...} | 固定長度數組 | 列表較短時餘下元素零初始化 |
| 動態分配 | int* a = malloc(N*sizeof(int)) | 堆上連續內存,需手動 free | 本質是指標,非數組 |
| sizeof 計算 | sizeof(arr) | 整個數組字節數 | 僅在定義作用域有效 |
sizeof(指標) 計算動態分配的元素個數。\0)。std::vector / std::array / std::span,彻底规避原始数组陷阱。