指針是C語言的核心特性之一,也是許多初學者感到棘手的概念。本文將系統講解指針的定義、操作、與數組/字符串的關係,以及實際編程中的常見應用場景。
指針變量的本質是存儲內存地址的變量。其定義語法為:
數據類型 *指針變量名;
例如 int *p; 表示定義一個指向 int 類型數據的指針變量 p。指針的核心作用只有一個:根據地址值訪問對應的存儲空間。
#include <stdio.h>
int main() {
int *p; // 定義指針變量 p,只能指向 int 類型數據
int a = 90;
p = &a; // p 指向變量 a 的地址
*p = 10; // 解引用:訪問 p 指向的存儲空間,修改 a 的值為 10
a = 20; // 直接修改 a
printf("%d\n", *p); // 輸出 20
return 0;
}
關鍵點:定義時的 * 是聲明標識,使用時的 * 是解引用操作符,兩者含義不同。
雖然所有指針在 64 位系統中均佔用 8 字節,但指針必須區分類型:
#include <stdio.h>
int main() {
char *cp; int *ap; long *bp;
printf("cp=%zd, ap=%zd, bp=%zd\n", sizeof(cp), sizeof(ap), sizeof(bp));
// 輸出均為 8(64位編譯器)
// 為什麼要分類型?因為編譯器需要知道解引用時從內存讀取多少字節。
return 0;
}
#include <stdio.h>
void change(int *p);
int main() {
int a = 10;
change(&a); // 傳遞 a 的地址
printf("a=%d\n", a); // 輸出 20
return 0;
}
void change(int *p) {
*p = 20; // 通過指針修改外部變量
}
#include <stdio.h>
void test(int a, int b, int *c, int *d);
int main() {
int a = 15, b = 10, he = 0, cha = 0;
test(a, b, &he, &cha);
printf("和是%d,差是%d", he, cha); // 輸出:和是25,差是5
return 0;
}
void test(int a, int b, int *c, int *d) {
*c = a + b;
*d = a - b;
}
數組名在大多數上下文中轉換為指向首元素的指針。指針算術運算會根據指針類型自動調整步長。
int ages[5] = {10, 11, 19, 78, 67};
int *p = ages; // p 指向首元素
// 1. 數組下標
ages[2]; // 19
// 2. 指針下標
p[2]; // 19
// 3. 指針算術 + 解引用
*(p + 2); // 19
int *ip; // ip+1 增加 4 字節 char *cp; // cp+1 增加 1 字節 double *dp; // dp+1 增加 8 字節
void change(int *array) { // 等價於 int array[]
printf("%d\n", array[2]); // 訪問第三個元素
}
int main() {
int ages[5] = {10, 11, 19, 78, 67};
change(ages); // 傳遞首元素地址
return 0;
}
| 定義方式 | 代碼示例 | 存儲區域 | 可修改性 | 適用場景 |
|---|---|---|---|---|
| 字符數組 | char name[] = "itcast"; | 棧區 | 內容可修改 | 字符串需頻繁修改 |
| 字符指針 | char *name = "itcast"; | 常量區 | 內容不可修改(嘗試修改會崩潰) | 字符串只讀、頻繁使用、共享常量池 |
char *name2 = "it";
char *name3 = "it";
// *name2 = 'T'; // 錯誤!程序崩潰,因為指向常量區
printf("%p\n%p\n", name2, name3); // 地址相同,編譯器優化共享常量
int main() {
char name[20];
printf("請輸入姓名:\n");
scanf("%s", name); // 讀取直到空白字符,自動添加 '\0'
return 0;
}
void test2() {
// 指針數組(字符串數組):每個元素是指針,指向常量區字符串
char *names[5] = {"jack", "rose", "jake"};
// 二維字符數組(字符串數組):每個元素是固定大小的字符數組,存儲在棧區
char names2[2][10] = {"jack", "rose"};
}
p + i 等價於 &p[i]。掌握指針是精通 C 語言的關鍵門檻,建議多動手實驗內存地址變化,結合調試器觀察堆棧分佈,將抽象概念具象化。