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

C 指針進階:指針常量 vs 常量指針、指針數組 vs 數組指針、函數指針 vs 指針函數、野指針

     編輯:關於C語言

核心概念辨析

指針是 C 語言最強大也最易混淆的特性。本文針對四組高頻易混概念進行定義、語法、用法與陷阱的系統梳理。

1. 指針常量 vs 常量指針

概念語法含義典型用途
常量指針
(Pointer to Constant)
const int *p;
int const *p;
指向 常量 的指針。
不能通過 *p 修改所指內容,但 p 本身可指向其他地址。
函數參數傳遞只讀緩衝區:
void print(const char *str);
指針常量
(Constant Pointer)
int *const p = &var; 指針 本身是常量。
初始化後不可改變指向地址,但可通過 *p 修改所指內容。
固定映射的硬體寄存器地址:
volatile uint32_t *const REG = (void*)0x4000;
指向常量的指針常量 const int *const p = &val; 指針與所指內容均不可修改。 只讀配置表基址。

口訣:從右向左讀,* 左邊有 const → 所指內容不可變;* 右邊有 const → 指針本身不可變。

2. 指針數組 vs 數組指針

概念語法本質示例
指針數組 int *arr[10]; 數組,元素類型為 int*。
佔用 10 × sizeof(int*) 字節。
字符串數組:char *argv[]
數組指針 int (*p)[10]; 指針,指向「含 10 個 int 的數組」。
佔用 sizeof(int*) 字節,步長為 10×sizeof(int)。
二維數組行指針:int (*p)[COLS] = matrix;

區別關鍵:[] 優先級高於 *,故 int *p[10] 先結合 p[10];加括號 int (*p)[10] 則先結合 *p。

3. 函數指針 vs 指針函數

概念語法本質應用場景
指針函數 int* func(int a); 函數,返回值類型為 int*。 返回動態分配的緩衝區指針、單例模式獲取實例指針。
函數指針 int (*pf)(int a); 指針,指向「接受 int、返回 int 的函數」。 回調函數、狀態機跳轉表、qsort 比較器、多態分發。

函數指針聲明讀法:pf 是一個指針 *pf,指向參數為 int、返回 int 的函數。

// 典型回調模式
typedef int (*cmp_fn)(const void*, const void*);
void sort(void *base, size_t n, size_t sz, cmp_fn cmp);

4. 野指針

定義:未初始化、已釋放、超出作用域的指針。其指向地址不可預期,解引用導致未定義行為(數據破壞、程序崩潰、安全漏洞)。

常見成因

  • 聲明未初始化:int *p; *p = 10;
  • 釋放後未置空:free(p); *p = 20;
  • 返回局部變量地址:int* foo() { int x; return &x; }

防範最佳實踐

  1. 聲明即初始化:int *p = NULL; 或 int *p = &var;
  2. 釋放即置空:free(p); p = NULL;
  3. 所有權清晰:誰分配誰釋放,避免雙重釋放。
  4. 靜態分析工具:Clang Static Analyzer、Coverity、PVS-Studio 可捕獲大多數野指針隱患。

總結

搞清「誰修飾誰」是理解指針聲明的核心。養成良好的初始化、置空習慣,配合編譯器警告(-Wall -Wextra -Werror)與靜態分析,能消除 90% 以上的指針相關 Bug。

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