許多初學者對指標「望而生畏」,甚至戲稱「見過暈車、暈血的,頭一回見暈指標的」。其實,「暈指標」與「暈車」同理:皆源於基礎不穩、心理恐懼與缺乏系統性理解。克服的關鍵在於「攻心」——建立正確的記憶體模型與變量本質認知,再輔以大量實戰演練。
先看一段經典代碼,若能輕鬆給出輸出,說明功底不錯:
#include <stdio.h>
int main(void)
{
char* str = "ABCDEFGHIJKL";
int* pInt = (int*)str;
printf("%c\n%c\n", *(str+1), *(char *)(pInt+1));
return 0;
}
解析:str+1 指向 'B';pInt 為 int*,pInt+1 向後偏移 sizeof(int) (通常 4 Bytes),指向 'E'。輸出為 B 和 E。此題考驗指標算術與類型轉換核心概念。
12, 'a', "abc") 與 符號常量 (如 #define PI 3.14)。記憶體中只有 0 和 1。**類型決定了解讀方式**:
int a = 97; -> 二進制按整數解讀 -> 顯示 97。char a = 'a'; -> 同樣二進制 (ASCII 97) -> 顯示 'a'。int *p = &a; -> 指標變量 p 存儲的二進制被解讀為地址。核心心法:變量值只是二進制序列,類型賦予其意義。
int a = 10;
int *p;
p = &a;

a 位於地址 0x2c406b24,值為 10。p 是指標變量,自身有地址,其**值**為 0x2c406b24 (即 a 的地址)。a:a (直接) 或 *p (間接/解引用)。請先思考再看答案:
char ch='a'; int a=(int)ch; -> ch 值 97, a 值 97。輸出 97 a。int add=0x123456; int *p=(int*)add; -> add 值為整數 0x123456; p 值為地址 0x123456; *p 解引用該地址 (危險操作,可能崩潰)。#define PI 3.14; int a=PI; -> 預處理展開為 int a=3.14;,隱式轉換 a=3。**合法**。printf("%d", PI); -> 展開為 printf("%d", 3.14);,格式不匹配,**未定義行為**。PI = 1.85; -> 編譯錯誤,宏常量非左值。char *str = "abcdef";
printf("%s", str); // 正常
*str = "fedcba"; // 錯誤!嘗試修改只讀記憶體 -> 段錯誤
str[2] = 'C'; // 同樣錯誤!修改字串常量內容
char *str = "abcdef";:編譯器在只讀區開闢房間存放 "abcdef",將鑰匙 (地址) 交給指標變量 str。你可以用鑰匙進房間**看 (讀)**,但絕不能**動 (寫)** 房間裡的傢俱,否則被「老闆」(作業系統) Kill 掉 (Segmentation Fault)。
char a[6] = {'A','B','C','D','E','F'}; 每元素 1 Byte,地址遞增 1。
陣列名 a 在大多數表達式中退化為指向首元素的指標:
sizeof(a) 計算整個陣列大小)。&a)。&a[0],最常見用法)。指標加減看類型:步長 = n * sizeof(類型)。
char* +1 -> 地址 +1。int* +1 -> 地址 +4。a[5] - a[3] = 2 (元素個數差),與類型無關。char a[3][4]; 編譯器視為「含 3 個元素的一維陣列,每元素是長度 4 的一維陣列」。

a 首地址 = &a[0]。a+1 步長為 sizeof(a[0]) = 4 Bytes (跳過一整行)。編譯器處理陣列下標 a[i] 時,內部轉換為 *(a+i)。**反彙編後不存在變量名,只有地址運算**。

上圖代碼輸出為 B 和 E,驗證了指標算術與二維陣列佈局。
char* 指向它屬危險操作,建議用 const char* 或陣列 char str[]。sizeof 不同)。理解記憶體模型,指標不再是「毒藥」,而是掌控底層的「利器」。