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

C/C++ 多維數組指針作函數參數傳遞詳解

     編輯:C 語言基礎

核心問題

在 C/C++ 中將多維數組傳遞給函數時,參數聲明與實際傳遞的地址類型必須精確匹配。本文通過一個計算學生成績的完整案例,系統梳理二維數組指針的定義、解引用與函數參數匹配規則。

案例需求

  • 輸入 3 位學生、各 4 門課的成績(共 12 個分數)。
  • 函數 search_score:顯示指定學生的 4 門課成績。
  • 函數 count_avg:計算所有 12 個分數的平均值。

完整代碼實現

#include <stdio.h>

void search_score(float (*p)[4], int n);  // 形參:指向含 4 個 float 的數組的指針
void count_avg(float *p, int n);          // 形參:指向 float 的指針(視為一維數組)

int main() {
    // 3 行 4 列,行代表學生,列代表課程
    static float scores[3][4] = {
        {97,   45.5, 66,   77},
        {88,   92.5, 78.5, 66},
        {83,   74.5, 92,   100}
    };

    // 顯示第 0 位學生(索引 0)的成績
    search_score(scores, 0);

    // 計算所有分數平均值
    // scores 退化為指向首行的指針,類型 float (*)[4]
    // *scores 即 scores[0],類型 float[4],退化為 float*,指向首個元素
    count_avg(*scores, 12);   // 等價於 count_avg(scores[0], 12) 或 count_avg(&scores[0][0], 12)

    return 0;
}

// 顯示第 n 位學生的 4 門課成績
void search_score(float (*p)[4], int n) {
    // p 指向第 n 行(一維數組 float[4])
    // p + n 指向第 n 行首地址
    // *(p + n) 解引用得到第 n 行數組,退化為指向該行首元素的指針
    // *(*(p + n) + i) 取第 i 門課分數
    for (int i = 0; i < 4; ++i) {
        printf("%7.2f", *(*(p + n) + i));
    }
    printf("\n");
}

// 計算 n 個 float 的平均值
void count_avg(float *p, int n) {
    float *end = p + n;  // 指向最後一個元素的下一個位置
    float sum = 0.0f;
    for (; p < end; ++p) {
        sum += *p;
    }
    printf("avg=%7.2f\n", sum / n);
}

關鍵類型解析

1. 二維數組名的類型與退化

  • scores 類型:float (*)[4](指向含 4 個 float 的數組的指針)。
  • scores[0] / *scores 類型:float[4],在表達式中退化為 float*,指向首元素 &scores[0][0]。
  • &scores[0][0] 類型:float*,同上。

2. 函數形參匹配規則

實參表達式類型匹配形參
scoresfloat (*)[4]float (*p)[4]
scores[0] / *scores / &scores[0][0]float*float *p

3. search_score 內部指針運算

float (*p)[4];  // p 是行指針
p + n;          // 偏移 n 行,類型仍為 float (*)[4]
*(p + n);       // 取第 n 行數組,類型 float[4],退化為 float*
*(*(p + n) + i) // 取第 n 行第 i 列元素

4. count_avg 視為一維連續內存

二維數組在內存中按行主序連續存儲,將首元素地址 &scores[0][0] 作為 float* 傳入,配合總元素個數 12,即可線性遍歷所有分數。

常見錯誤與避坑指南

  • 錯誤聲明 float *p[4]:這是指針數組(4 個 float*),而非指向二維數組的指針。正確寫法 float (*p)[4],括號不可省。
  • 傳遞 scores 給 float**:二維數組不是指針的指針,內存佈局無指針層級,會導致非法內存訪問。
  • 忽略列數常量:形參 float (*p)[4] 中的 4 必須與實際數組列數一致,否則指針運算偏移錯誤。C99 可用 VLA:float (*p)[cols]。

總結

多維數組傳參的本質是傳遞首元素地址,配合類型信息(列數)讓編譯器正確計算偏移。掌握 float (*p)[N] 與 float *p 兩種視角的轉換,是駕馭 C 語言指針系統的關鍵一環。

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