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

C 語言指標進階:多維陣列指標、函式指標與指標運算完整解析

     編輯:關於C語言

指標是 C 語言靈魂,掌握「指標與陣列的等價關係」、「多維陣列位址計算」、「函式指標回調機制」是邁向系統級開發的必經之路。本文從一維陣列指標切入,層層深入至二維陣列指標算術、指標陣列與陣列指標區別、函式指標實戰,並揭示 a[i][j] 編譯期如何轉譯為 *(*(a+i)+j)。

一維陣列與指標的核心等價關係

int a[5] = {0,1,2,3,4};
int *p = a;          // p 指向 a[0]
// 以下完全等價:
a[i]        == *(a + i) == *(p + i) == p[i]
&a[i]       == a + i  == p + i

關鍵差異:a 是常量指標(不可修改),p 是變數指標(可 p++、p = other)。

指標遍歷陣列三種風格

// 1. 索引風格
for (int i=0; i<5; ++i) p[i] = i;

// 2. 指標算術風格
for (int *p=a; p

指標作函式參數:模擬傳址呼叫

float average(float *arr, int n) {
    float sum = 0;
    for (int i=0; i

函式簽名 float *arr 與 float arr[] 完全等價,皆為指標。

二維陣列指標:位址計算完整推導

記憶體佈局(Row-major)

int a[3][4] = {
    {0, 1, 2, 3},
    {4, 5, 6, 7},
    {8, 9, 10, 11}
};
// 連續儲存:0,1,2,3, 4,5,6,7, 8,9,10,11
// 假設基址 1000,int 4 bytes
// a[0] @1000, a[1] @1016, a[2] @1032

位址等價關係表

表示式型別值(位址)含義
aint (*)[4]1000整個陣列位址 = 第 0 列位址
a[0] / *a / &a[0][0]int*1000第 0 列首元素位址
a+1 / &a[1] / *(a+1)int (*)[4] / int*1016第 1 列位址 / 第 1 列首元素位址
a[i] / *(a+i) / &a[i][0]int*1000+i*16第 i 列首元素位址
a[i]+j / *(a+i)+j / &a[i][j]int*1000+i*16+j*4第 i 列第 j 元素位址
*(*(a+i)+j) / a[i][j]int值第 i 列第 j 元素值

指向二維陣列的指標變數

int (*p)[4] = a;  // p 型別:指向 4 個 int 陣列的指標
// p+1 移動 16 bytes(跳過一整列)
// *p  等價 a[0](int*)
// p[i][j] 合法,編譯器知曉列寬 4

錯誤示範:int *p = a; 型別不匹配(int* vs int(*)[4]),雖然位址相同但指標算術會錯誤。

指標陣列 vs 二維陣列

// 指標陣列:每列長度可不同,記憶體不連續
char *names[] = {"Alice", "Bob", "Charlie"};
// names[0] → "Alice\0" (某處)
// names[1] → "Bob\0"   (另一處)

// 二維陣列:固定列寬,記憶體連續
char names2[][10] = {"Alice", "Bob", "Charlie"};
// names2[0] @基址, names2[1] @基址+10, ...

函式指標:回調與多態的基石

宣告與賦值

int add(int a, int b) { return a+b; }
int sub(int a, int b) { return a-b; }

int (*op)(int, int) = add;  // 函式指標變數
op = sub;                   // 執行期切換行為
printf("%d\n", op(3, 2));   // 1

實戰:通用排序回調

void sort(void *base, size_t n, size_t sz,
          int (*cmp)(const void*, const void*)) {
    // 簡易氣泡排序示意
    char *p = base;
    for (size_t i=0; i 0) {
                // swap bytes
                for (size_t k=0; k

這正是 qsort 的運作原理。

綜合練習:二維陣列轉置列印

void print_transpose(int (*a)[4], int rows, int cols) {
    for (int c = 0; c < cols; ++c) {
        for (int r = 0; r < rows; ++r)
            printf("%3d", a[r][c]);
        puts("");
    }
}
int main() {
    int a[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
    print_transpose(a, 3, 4);
    // 輸出:
    //   0  4  8
    //   1  5  9
    //   2  6 10
    //   3  7 11
}

總結:指標心智模型三部曲

  1. 型別決定算術:p+1 移動 sizeof(*p) bytes,二維陣列指標 int(*)[4] 移動一整列。
  2. 解參考降維:* 將指標型別降一維,*(*(a+i)+j) 逐層解參考取值。
  3. 陣列名退化規則:表達式中陣列名多退化為指向首元素的指標,sizeof、&、字串常數初始化除外。

內化這三條,指標不再是魔法,而是精確的記憶體導航儀。

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