該筆記整理自 阮一峰老師的《C語言教程》和部分網上資料
什麼是指標
指標就是一個代表某個記憶體地址的值
宣告和初始化指標變數
int a = 10;
// 宣告一個指標變數p,並將a的地址賦給p
int* p = &a;
// 輸出p的值(地址值)
printf("%p", p);
// 輸出p所指向的值
printf("%d", *p);
這個*
可以放在資料型別和變數名之間的任意位置,比如int * p;
,int *p;
等等,不過為了體現p
是一個指標變數,建議int* p;
%p
佔位符表示一個指標變數
野指標
野指標通常指的是那些指向了一個已釋放的記憶體區域、未分配的記憶體區域、或者指向了不可訪問的記憶體區域的指標
野指標如何產生的?
指標變數未經初始化,則該指標會隨機指向一個記憶體地址,因此應該儘量給指標變數初始化,如果不知道該賦啥值,就賦NULL
值
指標所指向的空間被釋放掉了,如果某個指標指向的空間被釋放了,應該立即將該指標指向NULL
陣列越界訪問
指標與數字加減
一般用於陣列指標或者字串指標
int* p = (int*) 0x100;
p += 2; // 此時p的值為0x108,因為指標偏移量和其資料型別一致,int型別的指標偏移量為4
使用指標遍歷列印陣列裡的元素
int arr[] = {1, 2, 3, 4, 5};
int* p = arr; // 此時p指向arr的第一個元素1
for (int i = 0; i < sizeof(arr) / sizeof(int); i ++) {
printf("%d\n", *p);
p ++;
}
指標之間的加減
指標之間的加法是違法的,會報錯
但是相同型別的指標之間的減法是合法的
int* p1 = (int*) 0x1009;
int* p2 = (int*) 0x1000;
int dist = p1 - p2; // dist的值為3
// 分析:因為 0x1009 - 0x1000 = 9
// int佔4位元組,所以 9 / 4 = 2 ... 1,多出來1位,這個多出來的1位被包含在第三個int元素裡,所以dist值為3
但是dist
可能會超過int
的範圍,所以為了程式的健壯性,建議這麼寫
#include <stddef.h>
int main() {
int* p1 = (int*) 0x1009;
int* p2 = (int*) 0x1000;
ptrdiff_t dist = p1 - p2;
return 0;
}
ptrdiff_t
型別專門被設計用來表示兩個指標之間的距離的,使用這種型別之前,需要引入stddef.h
踩雷日誌
交換兩個變數的值,錯誤程式碼:
int change(int x, int y) {
int* xp = &x;
int* yp = &y;
*xp = *xp ^ *yp;
*yp = *xp ^ *yp;
*xp = *xp ^ *yp;
}
錯誤點:忘記基本資料型別的傳參方式為值傳遞,即 新開一個空間,將值賦值進去,再讓引數指向新的空間
正確程式碼:
int change(int* x, int* y) {
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}