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

C語言 const 關鍵字完全指南:從基礎語法到指針修飾陷阱

     編輯:關於C語言

const 基本含義

const 是 C 語言類型限定符,表示只讀。編譯器會阻止對其修改,提高代碼安全性與可讀性。

核心區別:常量 vs 只讀變量


const int n = 5;
int a[n];  // ANSI C 錯誤:n 是「只讀變量」,非「編譯期常量」
  • 常量:字面量 5、'a'、枚舉常量、#define 宏。編譯期確定,存儲於只讀段。
  • 只讀變量:const int n。運行期分配內存,編譯器禁止寫入。
  • ANSI C 要求數組長度為常量表達式,const 變量不符合。C++ 則允許。

ANSI C 定義真正常量的方法


#define N 5           // 宏
enum { N = 5 };       // 枚舉常量 (推薦,有類型、作用域)

const 與指針:誰被修飾?

核心口訣:沿著 * 劃線,const 在左修飾指向的值,在右修飾指針本身。

情況一:修飾指向的值 (常量指針)


const int* p;      // p 指向 const int,值不可改,指針可改
int const* p;      // 同義
const int* p = &x; // ok
*p = 10;           // 錯誤
p = &y;            // ok

情況二:修飾指針本身 (指針常量)


int* const p = &x; // p 是常量指針,指針不可改,值可改
p = &y;            // 錯誤
*p = 10;           // ok

情況三:雙重修飾


const int* const p = &x; // 指針與值均不可改

情況四:帶括號的類型別名陷阱


typedef char* pStr;
const pStr p2 = "hello"; // 等價於 char* const p2
// const 修飾的是 pStr (即 char*),所以指針不可改
p2++; // 錯誤

規則:有括號時,括號內是整體類型,const 修飾整體。

const 與字符串字面量


char* p = "hello";     // 危險:字面量在 .rodata,p 應為 const char*
p[0] = 'H';            // UB:段錯誤

const char* p = "hello"; // 正確:編譯器阻止修改
char arr[] = "hello";    // 正確:複製到棧數組,可修改

const 在函數參數中的應用


// 輸入參數:防止誤修改,接受字面量/常量實參
void print(const char* str);
void process(const BigStruct* s); // 避免拷貝大結構體

// 輸出參數:不加 const
void getResult(int* out);

const 與類型轉換陷阱


const int ci = 10;
int* p = (int*)&ci;  // 強制去 const
*p = 20;             // UB:運行時可能崩潰或無效果 (取決於優化/存儲位置)

嚴禁 去除 const 後寫入,除非極少數硬體寄存器映射場景。

C99 新增:const 修飾數組參數


void foo(int arr[const]);          // 等價於 int* const arr
void bar(int arr[static 10]);      // 承諾至少 10 元素
void baz(const int arr[static 10]); // 只讀 + 至少 10 元素

總結速查表

聲明含義可修改指針可修改值
const int* p指向常量的指針是否
int const* p同上是否
int* const p常量指針否是
const int* const p常量指針指向常量否否
const pStr p (pStr=char*)常量指針否是

最佳實踐

  1. 默認給指針參數加 const,除非需要修改。
  2. 字符串字面量賦值給 const char*。
  3. 用 enum/#define 定義編譯期常量作為數組長度。
  4. 理解 typedef 陷阱:const pStr ≠ const char*。
  5. 嵌入式開發:寄存器映射用 volatile,只讀寄存器用 const volatile。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved