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

C語言數組與指針深度綁定:指針算術、多維數組與指針數組全解析

     編輯:關於C語言

核心洞察:數組名即首元素地址

在絕大多數表達式中,數組名 a 退化為指向首元素的指針 &a[0]。這是數組與指針互換的基石。

一、一維數組與指針算術

1. 等價關係

int a[10], *p = a; // p = &a[0]

p + i       == &a[i]       // 第 i 個元素地址
*(p + i)    == a[i]        // 第 i 個元素值
p[i]        == *(p + i)    // 指針也可用下標

2. 指針算術的縮放規則

p + i 的地址增量 = i * sizeof(*p)。編譯器自動根據指向類型縮放。

int a[10]; int *p = a;
p++; // 地址 +4 (假設 int 4 字節),指向 a[1]

double d[10]; double *q = d;
q++; // 地址 +8,指向 d[1]

3. 逆向下標技巧

int *p = &a[5];
p[-2] == a[3]; // 向前訪問,等價 *(p-2)

二、二維數組與指針:行指針的藝術

1. 二維數組內存佈局

int a[3][4] 按行優先連續存儲:

a[0][0] a[0][1] a[0][2] a[0][3]  // 第 0 行
a[1][0] a[1][1] a[1][2] a[1][3]  // 第 1 行
a[2][0] a[2][1] a[2][2] a[2][3]  // 第 2 行

2. 數組名的多重含義

表達式類型含義地址值(假設基址1000)
aint (*)[4]整個數組首地址 / 第 0 行首地址1000
a + 1int (*)[4]第 1 行首地址1016 (+4*4)
a[i]int*第 i 行首地址 (*(a+i))1000 + i*16
&aint (*)[3][4]整個數組地址 (類型不同!)1000

3. 元素地址的多種表示

// a[i][j] 等價形式
*(a[i] + j)        // 行指針 + 列偏移
*(*(a + i) + j)    // 數組指針 -> 行指針 -> 元素
(*(a + i))[j]      // 解引用行指針後下標

4. 指向行的指針:int (*p)[4]

int a[3][4];
int (*p)[4] = a; // p 指向整行 (4個int)

p++;       // 跳過一整行,地址 +16
*p         // 當前行首地址 (int*)
(*p)[j]    // 當前行第 j 個元素
*(p+i)+j   // 第 i 行第 j 個元素地址

三、指針數組 vs 數組指針:經典易混點

聲明含義用途
int *p[3];指針數組:3個 int*字符串數組、不規則矩陣、查找表
int (*p)[3];數組指針:指向 3個int 的數組二維數組行指針、矩陣運算

記憶口訣:括號優先。*p[3] 先結合 p[3] → 數組;(*p)[3] 先結合 *p → 指針。

指針數組經典:字符串處理

char *names[] = {"Alice", "Bob", "Charlie"}; // 指針數組
// 內存:names[0]→"Alice\0", names[1]→"Bob\0"...

for (int i = 0; i < 3; i++)
    printf("%s: length=%zu\n", names[i], strlen(names[i]));

四、函數參數傳遞:退化規則

// 以下三種聲明等價,參數均為 int*
void foo(int a[]);
void foo(int a[10]);
void foo(int *a);

// 二維數組:必須指定列數
void bar(int a[][4]);      // OK
void bar(int (*a)[4]);     // 等價
void bar(int a[3][4]);     // 3 被忽略
// void bar(int **a);      // 錯誤!類型不匹配

五、綜合實戰:矩陣轉置

void transpose(int rows, int cols, int (*src)[cols], int (*dst)[rows]) {
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)
            dst[j][i] = src[i][j];
}

int main() {
    int a[2][3] = {{1,2,3},{4,5,6}};
    int b[3][2];
    transpose(2, 3, a, b);
    // b = {{1,4},{2,5},{3,6}}
    return 0;
}

總結

  • 數組名在表達式中退化為首元素指針(除 sizeof、&、字符串字面量初始化)。
  • 指針算術自動按元素大小縮放,p[i] ≡ *(p+i)。
  • 二維數組:a 是行指針,a[i] 是列指針,int (*p)[cols] 是行指針變量。
  • 區分 int *p[N] (指針數組) 與 int (*p)[N] (數組指針)。
  • 函數參數:一維退化為指針,二維需保留列數類型。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved