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

C 語言指標完全掌握:從核心概念到進階運算與陣列關係

     編輯:關於C語言

前言:指標是 C 的靈魂

許多程式設計師精通 BASIC、Pascal 等語言,但指標是 C/C++ 獨有且最核心的特性。本文不重複教科書內容,專注於書本講不清、講不透的關鍵觀念,助你建立精準的指標心智模型。

第一章:指標的四大核心屬性

理解一個指標,必須搞清四個面向:

  1. 指標的型別:指標本身的型別
  2. 指標指向的型別:解參考後資料的型別
  3. 指標的值(指向的記憶體區塊):儲存的位址
  4. 指標本身佔用的記憶體:指標變數本身的儲存空間

範例宣告

(1) int *ptr;
(2) char *ptr;
(3) int **ptr;
(4) int (*ptr)[3];
(5) int *(*ptr)[4];

1. 指標的型別

去掉變數名,剩下的就是指標型別:

(1) int *      // 指向 int 的指標
(2) char *     // 指向 char 的指標
(3) int **     // 指向 int* 的指標
(4) int (*)[3] // 指向 int[3] 陣列的指標
(5) int *(*)[4] // 指向 int*[4] 陣列的指標

2. 指標指向的型別

去掉變數名與最左邊的 *,剩下的就是指向型別:

(1) int
(2) char
(3) int *
(4) int [3]
(5) int * [4]

關鍵洞見:指標型別與指向型別是兩個獨立概念。精通指標的關鍵在於將「型別」拆解為這兩個層面。

3. 指標的值與指向的記憶體區塊

指標值是一個位址(32 位元系統下為 32 位整數)。指向的記憶體區塊從該位址起始,長度為 sizeof(指向型別)。未初始化的指標指向區塊不存在或無意義。

4. 指標本身佔用的記憶體

32 位平台佔 4 位元組。判斷指標運算式是否為左值的依據:指標運算式結果是否已佔據明確記憶體。

第二章:指標算術運算

指標加減整數 不是 普通數值運算,步長由 sizeof(指向型別) 決定。

範例分析

char a[20];
int *ptr = a;  // 強制轉型,假設 a 位址為 0x1000
ptr++;         // ptr 變為 0x1004 ( sizeof(int)=4 )

ptr 原指向 a[0..3],現指向 a[4..7]。

遍歷陣列範例

int array[20];
int *ptr = array;
for (i = 0; i < 20; i++) {
    (*ptr)++;  // 元素值加 1
    ptr++;     // 移至下一元素
}

加減整數通則

  • ptr + n:位址增加 n * sizeof(指向型別) 位元組
  • ptr - n:位址減少 n * sizeof(指向型別) 位元組
  • 結果指標型別、指向型別不變
  • 可指向陣列邊界外(語法合法但存取風險自負)

第三章:& 與 * 運算子深度解析

& 取址運算子

  • 結果:指標
  • 型別:運算元型別 + *
  • 指向型別:運算元型別
  • 指向位址:運算元位址

* 間接運算子

  • 結果:指標指向的實體
  • 型別:指標指向型別
  • 佔用位址:指標指向位址

綜合範例

int a = 12, b;
int *p;
int **ptr;

p = &a;       // p: int*, 指向 a
*p = 24;      // *p 即 a,a 變 24
ptr = &p;     // ptr: int**, 指向 p
*ptr = &b;    // *ptr 是 int*,&b 也是 int*,賦值合法
**ptr = 34;   // **ptr 即 b,b 變 34

第四章:指標運算式與左值判斷

結果為指標的運算式稱為指標運算式。具備四大屬性,其中「本身佔用記憶體」決定是否為左值。

範例

int a, b;
int array[10];
int *pa = &a;        // &a 是指標運算式,非左值(臨時結果)
int **ptr = &pa;     // &pa 是左值(pa 有固定記憶體)
*ptr = &b;           // *ptr 是左值(即 pa)
pa = array;          // 陣列名轉型為指標
pa++;                // pa++ 是指標運算式,也是左值

第五章:陣列與指標的深層關係

陣列名的雙重身分

宣告 TYPE array[n] 時:

  1. 代表整個陣列:型別 TYPE[n],sizeof(array) 為整個陣列大小
  2. 轉型為指標:型別 TYPE*,指向第 0 元素,*array == array[0],array+3 == &array[3]

指標陣列範例

char *str[3] = {
    "Hello, this is a sample!",
    "Hi, good morning.",
    "Hello world"
};

strcpy(s, str[0]);   // 等同 strcpy(s, *str)
strcpy(s, str[1]);   // 等同 strcpy(s, *(str+1))

str 型別 char**,指向 char*。*str 型別 char*,指向第一個字串首字元。

指向陣列的指標

int array[10];
int (*ptr)[10] = &array; // ptr 型別 int(*)[10],指向整個陣列

此處 &array 取的是整個陣列位址,型別 int(*)[10],非 int**。

sizeof 陷阱

int (*ptr)[10];
sizeof(int(*)[10]) == 4   // 指標大小
sizeof(int[10]) == 40     // 陣列大小
sizeof(ptr) == 4          // 指標變數大小

sizeof 永遠測量運算元「自身型別」大小,不會自動解參考。

總結

指標精髓在於區分「指標型別」與「指向型別」,理解算術運算以「指向型別大小」為步長,掌握 &/* 的型別轉換規則,並看透陣列名在不同上下文的雙重角色。這些核心觀念是寫出正確、高效 C 程式的基石。

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