首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 數組退化為指針:函數參數 `const int arr[]` 實為 `const int*`,可接收單個 int 地址的原理與風險

     編輯:程式設計疑難解答

代碼現象

void print(const int arr[], int count) {
    for (size_t i = 0; i != count; ++i)
        cout << arr[i] << endl;
}

int main() {
    int i = 0;
    int j[2] = {0, 1};
    print(&i, 1); // ✅ 編譯通過,運行輸出 0
    print(j, 2);  // ✅ 正常輸出 0 1
}

核心原理:數組參數退化為指針

C++ 規定:**函數參數聲明為數組類型 `T arr[]` 或 `T arr[N]`,實際調整為指針類型 `T* arr`**。

  • `void print(const int arr[], int count)` **等價於** `void print(const int* arr, int count)`。
  • * `arr` 只是一個指針,指向內存地址。 * `arr[i]` 等價於 `*(arr + i)`,進行指針算術。

為什麼 `print(&i, 1)` 合法?

  1. `&i` 類型為 `int*` (單個 `int` 的地址)。
  2. 函數期望 `const int*`,`int*` 隱式轉換為 `const int*` (添加 const,安全)。
  3. `count = 1`,循環只訪問 `arr[0]` (即 `*arr`),**恰好是 `i` 的值**。
  4. **邏輯上視單個對象為長度為 1 的數組**,C++ 允許這種統一處理。

風險與最佳實踐

場景風險建議
傳遞單個對象地址 `&obj`調用者需確保 `count=1`,否則越界訪問未定義行為優先用函數重載 `void print(const int& val)` 處理單值
傳遞動態數組 `new int[n]`需手動傳遞長度,易出錯用 `std::vector` / `std::span` (C++20)
傳遞標準容器無法直接傳遞 `vector` (需 `.data()`)模板化 `template void print(const Container& c)`

現代 C++ 替代方案 (C++20 `std::span`)


#include 
#include 
#include 

void print(std::span data) { // 自動推導大小,攜帶邊界信息
    for (int x : data) cout << x << ' ';
    cout << '\n';
}

int main() {
    int i = 42;
    int arr[] = {1,2,3};
    std::vector v = {4,5,6};
    
    print({&i, 1});       // 隱式構造 span (指針+長度)
    print(arr);           // 數組隱式退化 (保留大小)
    print(v);             // vector 隱式轉換 (data()+size())
}

總結

函數參數 `const int arr[]` **本質是 `const int*`**,接收 `&i` (單個對象地址) 合法且常用於「統一處理單值與數組」的舊式代碼。現代 C++ 推薦 **`std::span` (C++20)** 或 **模板容器引用**,自動管理大小、避免退化、類型安全。

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