內存地址(普通指針)或偏移地址(成員指針)。
指向變量的指針,是數據內存的地址,指向函數的指針是代碼內存的地址,指向數據的指針指向數組開始位置的地址。
抽象點說,就是以一種統一的方式產生對不同數據結構的元素的引用
理解指針要注意以下幾個點:
-- 每個指針都有類型,類型決定指針移動時的步長(假設可移動:++ / -- / +n / -n)
-- 從內容上講,指針就是地址,尤其是在機器級層面上
-- 對指針進行類型轉換,僅僅是改變了解釋指針所指內存區域的方式,位模式沒有變
-- 指針可以指向函數,其值是函數對應機器代碼的第一條指令的地址
-- 指針和數組關系曖昧,如果你明白比例變址尋址,你就能清除數組名,下標,指針類型之間的關系,簡單說:數組名即基地址(立即數),下標即變址,指針類型即比例因子,而指針的值就是:偏移量 + 變址 * 比例因子 +基地址【IA32】,這樣你就明白數組名是個常量(在機器眼里就是個立即數,尋址時對變址沒有限制也就說明了C語言對下標越界不檢查)
指針是儲存地址的一個變量
指針變量儲存的就是一個地址, 可以有如下行為:
* 改變該變量的值;
* 取得該變量的值
這和其他變量是一樣的, 但是指針還可以做到:
* 改變該變量指向的那個地址的值
* 取得該變量指向的地址的值
這只是編譯器賦予指針的特定行為而已(通過& * 等語法), 在匯編層面大概就是間接尋址了.
因此指針就是儲存地址, 糾結「指針的指針」什么的可以退散了.
指針為什么要有類型
匯編中數據是沒有類型的, 所以指針的類型是編譯器在規定的, 通過了指針的類型檢查, 才能保證你少犯錯.
因為其他數據有類型, 所以指針也得有類型.
指針的類型表明: 你期望從這個地址里取出來的數據, 是什么類型的.
大部分時候, 我們想從一個 *int 指針中取出來的值總是 int, 只有在特殊情況下我們才會想把 int 當成 uint 取出來, 類型檢查就幫我們減少弄錯類型的可能.
另外, 類型也規定了指針移動的粒度, 你期望從一個 *int 取出一個 int, 那 *(int + 1) 如果是地址+1的話, 不就取出了奇怪的數字?所以這里的 *(int + 1) 的 1 起始是指代一個 sizeof(int), 這樣你才能方便地訪問連續的內存數據.
在匯編中大概就是 [arr + 4]. (32位限定), 編譯器根據指針的類型幫你做了這一步轉換.