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

深入理解 C 指標:第 4 章 指標與陣列筆記精華

     編輯:關於C

陣列 vs 指標:同中有異,異中有同

層面陣列 int a[10]指標 int *p
記憶體區域棧 (靜態/自動儲存期)堆 (malloc) 或任意位址
名稱本質**常量指標** (首元素位址,不可修改)**變量指標** (可指向任意位址)
sizeof整個陣列大小 (40 位元組)指標大小 (4/8 位元組)
賦值不可整體賦值可任意賦值

**核心口訣**:陣列名在表達式中 (除 sizeof、&、字串字面常數初始化外) 自動轉換為指向首元素的指標。

一維陣列與指標陣列


int a[5] = {1,2,3,4,5};
int *pa[5] = {&a[0], &a[1], &a[2], &a[3], &a[4]};  // 指標陣列,每元素存 int*
// 存取:a[i]  vs  *pa[i]

動態分配一維陣列


int *pv = (int *)malloc(5 * sizeof(int));
for (int i=0; i<5; ++i) pv[i] = i+1;  // pv[i] ≡ *(pv+i)
free(pv);

指標陣列動態分配 (鋸齒陣列)


int *arr[5];
for (int i=0; i<5; ++i) {
    arr[i] = (int *)malloc(sizeof(int));
    *arr[i] = i;
}
// 或
for (int i=0; i<5; ++i) {
    *(arr+i) = (int *)malloc(sizeof(int));
    **(arr+i) = i;  // 解引用兩次
}

分析:arr+i 是第 i 個指標的位址,*(arr+i) 取得該指標值 (指向 int 的位址),**(arr+i) 解引用到 int 本身。

二維陣列傳參與動態分配

靜態二維陣列傳參:退化為「指向固定寬度陣列的指標」


void init(int *arr, int rows, int cols) {  // 實為 int (*arr)[cols]
    for (int i=0; i<rows; ++i)
        for (int j=0; j<cols; ++j)
            *(arr + i*cols + j) = ++num;  // 手動線性化索引
}
int a[5][6];
init(&a[0][0], 5, 6);  // 必須傳首元素位址

形參 int *arr 僅保留一維資訊,故函數內**無法**用 arr[i][j] 語法,必須手動計算偏移。

動態分配真正的二維陣列 (連續記憶體)


int rows = 5, cols = 6;
int *flat = (int *)malloc(rows * cols * sizeof(int));  // 一塊連續區
// 存取:flat[i*cols + j]
free(flat);

動態分配指標陣列模擬二維 (非連續、行長可變)


int **mat = (int **)malloc(rows * sizeof(int *));
for (int i=0; i<rows; ++i)
    mat[i] = (int *)malloc(cols * sizeof(int));
// 存取:mat[i][j] ✓
// 釋放:
for (int i=0; i<rows; ++i) free(mat[i]);
free(mat);

此結構與 char **argv 同構,適合行長度不一的場景 (如文字行)。

程式碼範例精選

1. 指標陣列列印


int *num1[3];
int num2[3] = {1,2,3};
for (int i=0; i<3; ++i) num1[i] = &num2[i];
for (int i=0; i<3; ++i) printf("%4d", *num1[i]);

2. 通用二維陣列初始化/列印 (線性化索引)


void arr_init(int *arr, int rows, int cols) {
    int val = 1;
    for (int i=0; i<rows; ++i)
        for (int j=0; j<cols; ++j)
            *(arr + i*cols + j) = val++;
}
void arr_print(int *arr, int rows, int cols) {
    for (int i=0; i<rows; ++i) {
        for (int j=0; j<cols; ++j)
            printf("%4d", *(arr + i*cols + j));
        putchar('\n');
    }
}
int main() {
    int a[5][6], b[7][8];
    arr_init(&a[0][0], 5, 6); arr_print(&a[0][0], 5, 6);
    arr_init(&b[0][0], 7, 8); arr_print(&b[0][0], 7, 8);
}

避坑指南

  1. 不要對形參陣列用 sizeof:已退化為指標,只得指標大小。
  2. 二維陣列參數保留次維:void f(int a[][COLS]) 或 void f(int (*a)[COLS]),COLS 必須為常量。
  3. malloc 記得配對 free:指標陣列需逐行 free 再 free 主陣列。
  4. 字串指標陣列:char *strs[] 本質同 int **,操作邏輯完全一致。

結語

指標與陣列的關係是 C 語言最微妙也最核心的主題。**記住「陣列名在絕大多數場合轉換為指標」,並搞清記憶體佈局 (連續 vs 分散)、生命週期 (棧 vs 堆)、型別資訊保留程度 (一維全失 vs 二維保留次維)**,即可駕馭各種複雜資料結構。

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