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

徹底搞定 C 語言指針(四):const 與指針的四種組合語義完整解析

     編輯:關於C語言

徹底搞定 C 語言指針(四):const 與指針的四種組合語義完整解析

const 與指針結合產生四種基本聲明模式,搞清**「誰被修飾、誰只讀」**是寫出正確、可維護代碼的關鍵。本文從 int i 切入,層層遞進解析四種模式語義、代碼驗證與記憶口訣。

基礎認知:const 修飾變量 → 符號常量


const int ic = 20;  // ic 成為只讀符號,不可修改
// ic = 40; // 編譯錯誤
  • const int 與 int const **完全等價** — const 修飾緊隨其后的類型關鍵字
  • 此時 ic 不再是「變量」,而是「只讀符號常量」

四大核心模式語義對照表

聲明等價寫法const 修飾對象指針值可改?指向值可改?俗稱
const int *pint const *p*p (指向的值)✅ 是❌ 否指向常量的指針
int *const p無p (指針本身)❌ 否✅ 是常量指針
const int *const pint const *const p*p 和 p 皆修飾❌ 否❌ 否指向常量的常量指針
int *p無無✅ 是✅ 是普通指針

逐模式代碼驗證與語義分析

1. const int *p (或 int const *p) — 指向常量的指針


int i1 = 30, i2 = 40;
const int *p = &i1;  // 初始化指向 i1
p = &i2;             // ✅ 合法:指針值可改,重新指向 i2
// *p = 80;          // ❌ 非法:不能通過 p 修改指向的值
i2 = 80;             // ✅ 合法:直接修改 i2 本身 (i2 非 const)
printf("%d", *p);    // 輸出 80

語義:p 是變量 (可指向別處),*p 是只讀視圖。
典型用途:函數參數 void func(const int *p) 承諾不修改調用者數據。

2. int *const p — 常量指針 (指針本身不可變)


int i1 = 30, i2 = 40;
int *const p = &i1;  // 初始化時必須賦值,後不可改
// p = &i2;          // ❌ 非法:指針值不可修改
*p = 80;             // ✅ 合法:可通過 p 修改 i1
printf("%d", *p);    // 輸出 80

語義:p 綁定初始地址終身不變,但可修改該地址存儲的值。
典型用途:硬件寄存器映射 volatile int *const REG = (int*)0x40001000; — 地址固定,值可讀寫。

3. const int *const p — 雙重只讀


int i = 30;
const int *const p = &i; // 初始化後 p 與 *p 皆不可改
// p = &i;   // ❌
// *p = 40;  // ❌
printf("%d", *p); // 唯一操作:只讀

語義:指針與指向值雙重保護,最高級只讀承諾。

三種進階場景補充

場景一:普通指針指向 const int 變量


const int ci = 40;
int *p;
// p = &ci;        // ❌ 編譯錯:const 地址不能賦給非 const 指針 (丟棄 const 資格)
p = (int*)&ci;    // ✅ 強制轉型編譯通過,但 *p = 80 運行時未定義行為 (可能崩潰/無效)

教訓:絕不 通過強制轉型移除 const 然後修改,違反只讀契約導致 UB。

場景二:const int *p 指向 const int 變量


const int ci = 40;
const int *p = &ci; // 類型完美匹配,雙重只讀保護

場景三:函數參數傳遞中的 const 策略


// 1. 僅讀取數據,不修改 → const int * / const char *
void printArray(const int *arr, size_t n);

// 2. 輸出參數,需修改指向內容 → int * (無 const)
void readIntoArray(int *arr, size_t n);

// 3. 指針本身不應被修改 (罕見) → int *const
void legacyAPI(int *const handle); // handle 地址固定

一句話記憶口訣

「const 在 * 左邊 → 鎖定指向值 (*p 不可改);const 在 * 右邊 → 鎖定指針本身 (p 不可改)。」

讀聲明時**從右向左**讀:int *const p → p is a const pointer to int;const int *p → p is a pointer to const int。

下篇預告

函數參數傳遞三大模式深度對決:**指針傳遞 vs 值傳遞 vs 引用傳遞 (C++)** — 為什麼以為 a,b 代替了 x,y 卻發現原值未變?揭開「傳遞假象」背後的棧幀真相。

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