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

C/C++ 陣列排序實戰:陣列名與指標作為函數參數的本質區別

     編輯:關於C++

核心事實:陣列作為函數參數退化為指標

void reverse_array(int arr[], int n);   // 等價於
void reverse_array(int *arr, int n);    // 等價於
void reverse_array(int arr[10], int n); // 10 被忽略,仍退化為指標

**函數內部無法得知原始陣列大小**,必須額外傳遞 n。

實作一:陣列名(退化指標)版本

void reverse(int x[], int n) {
    int m = (n - 1) / 2;  // 交換次數
    for (int i = 0; i <= m; ++i) {
        int j = n - 1 - i;      // 對稱位置
        int temp = x[i];
        x[i] = x[j];
        x[j] = temp;
    }
}
// 呼叫:reverse(a, 10);  // a 退化為 &a[0]

記憶體共享驗證

主程式 a[10] 與函數參數 x[] **共享同一塊記憶體**,函數內交換直接修改原陣列。

實作二:顯式指標版本

void reverse_ptr(int *x, int n) {
    int *i = x;                 // 指向首元素
    int *p = x + (n - 1) / 2;   // 指向中間元素(終止條件)
    int *j = x + n - 1;         // 指向尾元素
    for (; i <= p; ++i, --j) {
        int temp = *i;
        *i = *j;
        *j = temp;
    }
}

指標運算優勢

  • 無需索引變數 i、j,直接移動指標。
  • 更貼近機器指令,早期編譯器優化效果更好(現代編譯器兩者等價)。
  • 統一了「迭代器」概念,為 STL 算法設計奠基。

    兩版本本質對比

    維度陣列名版本 int x[]指標版本 int *x
    語意暗示「這是一個陣列」明確「這是一個指標」
    內部操作x[i] 索引訪問*x 解引用 + 指標算術
    編譯器視角完全相同,均退化為 int*完全相同
    可讀性初學者友好資深開發者偏好
    現代 C++ 建議棄用兩者,改用 std::span<T> (C++20) 或迭代器對 std::reverse(begin, end)

    現代 C++ 最佳實踐

    #include <algorithm>
    #include <vector>
    #include <span>  // C++20
    
    // C++98 風格
    void legacy_reverse(int *arr, int n) {
        std::reverse(arr, arr + n);
    }
    
    // C++20 std::span:保留大小、邊界檢查、支援陣列/容器/指標
    void modern_reverse(std::span<int> s) {
        std::reverse(s.begin(), s.end());
    }
    
    // 容器版本
    void container_reverse(std::vector<int> &v) {
        std::reverse(v.begin(), v.end());
    }
    
    int main() {
        int a[10] = {0,1,2,3,4,5,6,7,8,9};
        modern_reverse(a);        // 陣列隱式轉 span
        std::vector<int> v = {0,1,2,3,4,5,6,7,8,9};
        container_reverse(v);
    }

    常見錯誤與避坑

    錯誤代碼問題修正
    void f(int a[]) { int n = sizeof(a)/sizeof(a[0]); }sizeof(a) 取得指標大小,非陣列大小額外傳遞 size 參數或用 std::span
    void f(int a[10]) { ... } 傳入 5 元素陣列參數退化為指標,編譯器不檢查大小用 std::array<int,10> 強制大小
    函數內 delete[] arr;釋放非堆記憶體 → 未定義行為只有 new[] 分配的記憶體才能 delete[]

    總結

    1. 陣列作為參數**必然退化為指標**,int a[]、int *a、int a[N] 在函數簽名中**完全等價**。
    2. 函數內修改參數內容**直接修改原始陣列**,因為共享記憶體地址。
    3. 指標版本用指標算術替代索引,本質相同,現代編譯器優化後無效能差異。
    4. **新代碼請使用 std::span、std::vector、std::array + STL 算法**,獲得型別安全、邊界檢查、大小感知、意圖清晰的介面。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved