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

C 語言指針運算與指針數組關係深度解析(三)

     編輯:關於C語言

前言

指針運算是 C 語言靈活高效操作記憶體的核心機制。本文詳細闡述指針比較、指針-整數加減、指針差值運算的規則與語義,並揭示指針與數組「等價但不相同」的深層關係,為掌握指針算術奠定堅實基礎。

一、指針允許的運算類別

1. 指針比較(關係運算)

  • 前提:兩指針指向**同一數組**(或同一分配塊)內的元素,比較才有定義語義。
  • 支援運算符:== != < > <= >=。
  • 語義:比較在數組中的相對位置。p < q 表示 p 指向的元素在 q 之前。
  • 未定義行為:指向不同數組、不同 malloc 塊、一個指向數組一個指向標量的指針比較(除 ==/!= 外)。

2. 指針與整數加減

  • 形式:p + n、p - n、n + p(n 為整數)。
  • 語義:結果指向偏移 n 個**元素**的位置(非位元組)。
  • 縮放因子:編譯器自動乘以 sizeof(*p)(所指類型大小)。
類型sizeofp+1 位移位元組
char11
short/int (16-bit)22
long/float44
double88
結構/聯合結構大小結構大小

例如:int *p 指向 a[0],則 p+3 指向 a[3],位移 6 位元組。

3. 指針差值(減法)

  • 前提:同一數組內兩指針。
  • 結果:p - q 為 **ptrdiff_t** 有符號整數,表示相隔元素個數(非位元組)。
  • 縮放規則:位元組差值除以 sizeof(*p)。
  • 應用:計算數組長度、當前索引、剩餘元素數。

二、指針與數組:等價但不相同

核心宣稱

「任何能由數組下標完成的操作,均可用指針實現;指針代碼更緊湊、更靈活。」

關鍵等價關係表(以 int a[5]、int *pa = a 為例)

數組表示指針表示語義
apa首元素地址 (&a[0])
a[i]*(pa + i)第 i 元素值
&a[i]pa + i第 i 元素地址
sizeof(a)sizeof(*pa)*5整個數組大小 (指針失效)

本質區別

  • 數組名:常量地址,**不可修改**(a++ 非法),編譯期確定大小。
  • 指針變量:可修改左值(**可賦值、自增、自減**),運行時動態綁定。
  • sizeof:sizeof(a) = 整個數組大小;sizeof(pa) = 指針大小。

指針遍歷數組經典模式

/* 模式 1:指針自增遍歷 */
int *pa = a;
for (int i = 0; i < 5; i++) {
    *pa = i;      // 賦值
    pa++;         // 移至下一元素
}

/* 模式 2:指針作循環條件 */
int *pend = a + 5;
for (int *p = a; p < pend; p++) {
    printf("%d ", *p);
}

/* 模式 3:指針差值計算已處理數 */
int *pa = a;
int *start = pa;
while (pa < a + 5) *pa++ = 0;
printf("Cleared %td elements\n", pa - start);

三、實戰陷阱與最佳實踐

陷阱說明對策
指針越界訪問p + n 超出分配範圍(含 a+5 合法但不可解引用)嚴守 [base, base+size) 半開區間
不同數組指針相減未定義行為僅在同一數組/塊內相減
void* 算術GNU 擴展允許按 1 字節算術,標準 C 禁止轉為 char* 再運算
指針差值溢出極大數組超過 PTRDIFF_MAX使用 size_t 索引而非指針差值

總結

指針運算的三大支柱——**比較、整數加減、差值**——均建立在「以元素為單位、按類型大小縮放」的統一模型之上。指針與數組在**表達式語境下等價**(a[i] ≡ *(a+i)),但**本質不同**(常量 vs 變量、sizeof 語義)。深諳此道,方能寫出 memcpy、qsort 回調、環形緩衝區等經典系統級代碼。

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