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

C 語言指針完全指南:從基礎操作到函數參數傳遞與陣列應用

     編輯:關於C

指針是 C 語言的靈魂,也是初學者最大的攔路虎。本文系統梳理指針定義、運算、函數參數傳遞、陣列關係等核心知識點,配合完整可編譯代碼範例,助你建立清晰的指針心智模型。

1. 指針變量基礎:定義、賦值與引用

1.1 定義語法

類型標識符 *指針變量名;
// 例
int *pa, *pb;      // pa、pb 均為 int*
float *q;          // q 為 float*

關鍵:* 屬於類型聲明一部分,變量名是 pa 而非 *pa。

1.2 賦值方式

int n1, n2;
int *p1, *p2, *p3;
p1 = &n1;        // 取址賦值
p2 = &n2;
p3 = p2;         // 指針間賦值(共享指向)

類型匹配原則:指針類型必須與目標變量類型一致,void* 為通用指針可接收任意類型位址。

1.3 間接訪問(解引用)

pi = &x;
x = 1;
y = *pi + 9;   // 等價於 y = x + 9

*pi 與 x 成為同一記憶體單元的別名,修改任一者即修改該單元值。

2. 指針運算:算術、比較與優先級

2.1 算術運算

  • p++ / p--:按所指類型大小移動位址(如 int* 移 4 位元組)。
  • p + n:向後偏移 n 個元素位置。
  • 禁止:指針相加、指針乘除、指針與浮點數運算。

2.2 優先級經典陷阱

int a = 10, *p = &a;
*p++   // 等價 *(p++):取值後 p 移向下一個 int
(*p)++ // 等價 ++(*p):a 變為 11,p 不動
*p+1   // 等價 (*p)+1:值為 11,不修改 a

2.3 比較與減法

  • 同類型指針可比較(== != < > <= >=),高位址大於低位址。
  • 同類型指針相減得 ptrdiff_t,值為元素個數差(位址差 / sizeof(類型))。
  • 皆可與 NULL (0) 比較判斷空指針。

3. 指針作為函數參數:實現多值返回與數據修改

3.1 傳值 vs 傳址

void fun(int num) { num = 20; }  // 傳值:不影響實參
void fun(int *p) { *p = 20; }    // 傳址:修改實參指向的值

3.2 交換兩數的三種嘗試

// ❌ 1. 傳值:僅交換形參副本
void swap1(int x, int y) { int t=x; x=y; y=t; }

// ❌ 2. 傳指針但交換指針本身:僅交換區域指針變量
void swap2(int *p1, int *p2) { int *t=p1; p1=p2; p2=t; }

// ✅ 3. 傳指針並交換指向的內容:真正實現交換
void swap3(int *p1, int *p2) { int t=*p1; *p1=*p2; *p2=t; }

4. 指針與一維陣列:深度綁定關係

4.1 陣列名即首元素位址

int a[5], *p = a;        // p 指向 a[0]
int *q = &a[3];          // q 指向 a[3]

4.2 兩種訪問風格

// 索引法
for (i=0; i<10; i++) scanf("%d", pa+i), printf("%d ", *(pa+i));

// 指針法(更高效,編譯器易優化)
for (pa = arr; pa < arr+10; pa++) scanf("%d", pa);
for (pa = arr; pa < arr+10; pa++) printf("%d ", *pa);

4.3 實戰:統計正數個數

int a[10], *p, count = 0;
for (p = a; p < a+10; p++)
    if (*p > 0) { count++; printf("%d ", *p); }

5. 陣列作為函數參數:退化為指針

陣列參數退化為指針,實際傳遞首元素位址(地址傳遞),函數內修改陣列元素影響原陣列。

void input(int a[10], int n) { for(i=0;i

6. 綜合示例:指針運算觀察器

int main() {
    int a=10,b=30,*p1=&a,*p2=&b;
    printf("%d %d %d %d %p %p %p %p\n",a,b,*p1,*p2,p1,p2,&p1,&p2);
    a++; (*p2)++;
    printf("%d %d %d %d %p %p %p %p\n",a,b,*p1,*p2,p1,p2,&p1,&p2);
    *p1++; *p2--;   // 注意優先級:*p1++ 等價 *(p1++)
    printf("%d %d %d %d %p %p %p %p\n",a,b,*p1,*p2,p1,p2,&p1,&p2);
    printf("%td %td\n", p1-p2, p2-p1);  // 指針減法
}

總結:指針掌握檢查清單

  1. ✅ 區分 指針變量本身 (位址) 與 指向的值 (解引用)
  2. ✅ 熟練 & 取址、* 解引用、++/-- 移動元素
  3. ✅ 理解陣列名退化規則,靈活切換索引/指針訪問
  4. ✅ 函數需修改實參時傳址(指針),且在函數內解引用賦值
  5. ✅ 警惕野指針、懸空指針、越界訪問,養成 NULL 檢查習慣

指針不是魔法,而是記憶體位址的直接操作介面。畫圖(方框表記憶體、箭頭表指向)是練就指針直覺的最佳方法。

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