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

C 語言語義陷阱:陣列與指標的訪問差異

     編輯:關於C

前言

陣列與指標是 C 語言最核心也最易混淆的概念。許多教材僅說「陣列名是指標」,實則過度簡化。本文從 **宣告與定義**、**記憶體訪問機制**、**編譯器處理** 三個層面,釐清兩者本質差異。

宣告 vs 定義

  • 定義:建立物件,**配置記憶體**,一個程式僅能出現一次 (如 int a[10];)。
  • 宣告:僅告知編譯器「此名稱對應某處已定義的物件」,**不配置記憶體**,可多次出現 (如 extern int a[];)。

三種宣告情境:

  1. 外部陣列宣告 (extern int a[];)
  2. 陣列定義 (int a[10];) — 宣告的特例
  3. 函數參數宣告 (void f(int a[]);) — **唯一會退化為指標的宣告**

記憶體訪問機制的根本差異

**賦值 x = y 中**:x 代表 **位址 (左值)**,y 代表 **內容 (右值)**。編譯期可知所有變數位址 (左值);執行期才知內容 (右值)。

陣列訪問

a[i]:陣列名 a 在編譯期即為 **首元素位址 (常數左值)**。編譯器直接產生指令:位址 = a + i * sizeof(element),然後存取該位址。
→ **單次間接存取**。

指標訪問

*p 或 p[i]:指標 p 本身是一個 **變數**,有其儲存位址 (左值) 及儲存內容 (右值,即目標位址)。
步驟:
1. 讀取 p 的 **儲存位址** 取得 **目標位址** (右值)。
2. 用該目標位址存取資料。
→ **雙重間接存取**。

陣列訪問示意 指標訪問示意

外部宣告匹配規則

  • char a[100]; 定義 → extern char a[]; 或 extern char a[100]; 宣告:**合法** (皆表達「此處有陣列」)。
  • char *p = "str"; 定義 → extern char *p; 宣告:**合法**。
  • char a[100]; 定義 → extern char *a; 宣告:**錯誤**!宣告說「有個指標變數」,實際卻是陣列,會導致錯誤的雙重間接存取。

指標初始化陷阱

char *p = "breadfruit";
  • 字串常值通常置於 **唯讀區段**。
  • 嘗試修改 p[0] = 'B'; → **未定義行為** (通常段錯)。
  • 若需可修改緩衝區:char p[] = "breadfruit"; (陣列定義,內容複製到堆疊/資料段)。

總結

  1. **陣列名在表達式中** 退化為 **首元素指標 (右值)**;**指標變數** 本身有左值與右值。
  2. **函數參數宣告** 是**唯一**陣列退化為指標的宣告場合。
  3. extern 宣告必須與定義的 **物件類型** 匹配 (陣列對陣列,指標對指標)。
  4. 字串常值初始化指標指向唯讀記憶體,切勿修改。

下一篇將討論函數調用中的陣列/指標行為、何時可互換、以及兩者的深層聯繫。

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