1. 內存和地址
??在了解指針前,我們需要知道內存和地址是什么。
1.1 內存
? ? ? ?首先來看內存。舉個例子:當你在酒店找房間時,你并不是一層一層一間一間找,而是通過酒店為每間房子設置的門牌號直接找到你的房間,這樣的效率就會快很多。
? ? ? ?把上面的例子投影到計算機中:CPU在處理數據的時候,需要在內存中取數據,處理后的數據又會放回到內存中。內存空間管理時就會把內存劃分為一個個內存單元,每個內存單元大小設置為一字節。每個內存單元也有其相應的編號,這樣CPU就可以通過編號快速找到一個內存單元。這個編號在計算機中我們稱它為地址。C語言中給地址起了個新的名字,叫指針。因此我們可以理解為:內存單元的編號==地址==指針。
1.2 如何理解編址
? ? ? ?首先,需要知道,計算機內部是有很多硬件單元的,各個硬件單元相互工作時是通過“線”連接起來的。而CPU和內存之間也是有?量的數據交互的,所 以,兩者必須也?線連起來。我們今天只關心地址總線(還有數據總線和控制總線)。當CPU在訪問某個內存單元時,必須知道該內存單元在哪個位置,因此需要給每個內存單元進行編址。
? ? ? ?計算機中的編址,并不是把每個字節的地址記錄 下來,?是通過硬件設計完成的。就像吉他和鋼琴等樂器一樣,琴弦和鋼琴鍵上并沒有標注 do、re、mi......。但是演奏者總能精準地找到在什么位置,這是大家約定俗成的。
? ? ? ?硬件編制也是如此,32位機器就有32根地址總線,每一位都有 0 和 1 兩種結果,32根像就能表示出 2 的 32 次方種結果,每一種排列都表示一個地址,64位機器以此類推。地址信息被下達給內存,在內存上,就可以找到 該地址對應的數據,將數據在通過數據總線傳? CPU內寄存器。
2.指針變量和地址
2.1 取地址操作符(&)
? ? ? ?在C語言中創建變量的本質就是向內存申請空間。如圖:
? ? ? ? 右下角的內存中 & 為取地址操作符,圖中為取出 x 的地址,是一個單目操作符。我們之前學的 a&b 表示 a 按位與 b ,兩者不一樣。上述代碼就是創建了一個整型變量 x ,在內存中申請了 4 個字節用來存放 4。當我們打印 x 的地址時,就會發現這個內存單元中正好存放的是 4。
2.2 指針變量和解引用操作符
2.2.1指針變量
? ? ? ? 我們通過取地址操作符(&)得到一個變量的地址,我們通過指針變量將它存放起來,便于使用例如:
#include <stdio.h>
int main()
{int x = 4;int * p = &x;//取出x的地址放到指針變量p中return 0;
}
? ? ? ? 指針變量也是一種變量,只不過讓它是用來存放地址的,變量中的值都是地址。
2.2.2 如何理解指針變量
? ? ? ? 剛剛的定義的 int * p 中,* 說明 p 是一個指針變量,int 表示 p 指向的的類型是整型。同理如果有個 char、double、等類型的變量,他們的地址就要分別放在 char*、double* 中。
2.2.3 解引用操作符
? ? ? ? 我們將地址存起來肯定是要使用的,使用時我們就會用到解引用操作符(*)。
? ? ? ? 上圖中就使用了解引用操作符我們通過 *p 找到了 x 并且修改了 x 的值,我們修改時并沒有寫 x = 0 ,而是直接通過指針變量來修改,即 *p=0 ,這樣寫代碼時會更加靈活。
2.3 指針變量的大小
? ? ? ??32位機器有32根地址總線,那么它就需要 4 個字節來存儲地址(1個字節 8 個比特位,4個字節剛好 32 個比特位),同理 64 位機器則需要 8 個字節來存儲地址。同時我們要注意指針變量的大小和類型是無關的,只要指針類型的變量,在相同的平臺下,大小都是相同的。不管指針變量是? char 還是 int ,他們在32位機器下都是 4 個字節,在 64 位機器下都是 8 個字節。
3.指針變量類型的意義
3.1指針的解引用
? ? ? ? 讓我們來對比下面兩段代碼:
? ? ? ? ?我們發現 int* 和 char* 修改的字節不同,因此:指針的類型決定了對指針解引用的時候有多大的權限(?次能操作?個字節)。 ?如?char* 的指針解引用就只能訪問一個字節,而 int* 的指針的解引?就能訪問四個字節。
3.2 指針+-整數
? ? ? ? 同樣的,對指針+-時,不同的指針變量的類型所移動的距離也不同。若對 int* 進行+/-1時,會一次移動四個字節,而對 char* 進行+/-1時則一次移動一個字節。
3.3 void*指針
? ? ? ? ?void* 表示無具體類型的指針。這種類型的指針可以接受任意類型的地址,但是我們不能直接對這種類型的指針進行+/-整數和對指針的解引用,需要進行強制類型轉換。?般 void* 類型的指針是使?在函數參數的部分,?來接收不同類型數據的地址,這樣的設計可以實現泛型編程的效果。使得?個函數來處理多種類型的數據。
4.指針運算
4.1 指針+-整數
? ? ? ? 數組在內存中是連續存放的,因此只要知道第?個元素的地址后,我們可以通過加減操作來獲取后面的所有元素。
4.2 指針-指針
? ? ? ??
? ? ? ?由圖可得,指針-指針所得帶的結果是兩個指針之間的元素個數,但前提是這兩個指針指向的是同一塊內存空間。
? ? ? ?另外,指針也能進行關系運算。
? ? ? ??