簡介
指針一直是C語言和C++語言最難了解的一部分,無論是C語言和C++語言,複雜的資料結構都是離不開指針的運用,是以必須掌握好指針這個資料類型,你才能夠在閱讀架構代碼時,遊刃有餘。今天我們從指針的本質來重新了解指針這個資料類型。
1.指針的本質
指針是用來儲存位址的一個變量,那麼變量都是儲存在記憶體中,而記憶體其實就是一組有序位元組組成的數組,每個位元組有唯一的記憶體位址。CPU 通過記憶體尋址對存儲在記憶體中的某個指定資料對象的位址進行定位。說白了,CPU就是通過位址去查找存儲在記憶體中的資料。下面我們看看如下示意圖:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SOlNTOxUWZ3UTZ3ATMiljNldzY3MDN2MzN1UzNyMmYk9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
這是一個 4GB 的記憶體,可以存放 2^32 個位元組的資料。左側的連續的十六進制編号就是記憶體位址,每個記憶體位址對應一個位元組的記憶體空間。而指針變量儲存的就是這個編号,也即記憶體位址。指針本身也是有記憶體位址來儲存這個變量的。
2.為什麼要使用指針
在C語言中,指針的使用非常廣泛,因為使用指針往往可以生成更高效、更緊湊的代碼。總的來說,使用指針有如下好處:
1)指針的使用使得不同區域的代碼可以輕易的共享記憶體資料,這樣可以使程式更為快速高效;
2)C語言中一些複雜的資料結構往往需要使用指針來建構,如連結清單、二叉樹等;
3)C語言是傳值調用,而有些操作傳值調用是無法完成的,如通過被調函數修改調用函數的對象,但是這種操作可以由指針來完成,而且并不違背傳值調用。
3.指針定義和初始化
下面我們再來看看下面例子:
int a = 100;
int *p = &a;
int **p2 = &p1;
p2 p1 a
&p1 -> &a -> 100
為了友善了解,我們來打個比喻:
定義的a,p,p2都是一個盒子,他們都有自己位址空間,友善别人找到它
a是一個盒子,用來裝100這個資料,a本身有位址;
p也是一個盒子,用來裝a的位址,p本身也有位址;
P2也是一個盒子,用來裝p的位址,p2本身也有位址;
a和p和p2變量本身都是代表盒子裡面的東西
=》盒子裡面裝可能是值,也可能是位址,例如a就是值,p和p2都是位址;
“*”的操作(隻對指針變量),就是取出盒子裡面位址,去打開另一個盒子那東西
=》相當于,從抽底裡面取出一把鑰匙,去打開另一個抽底去拿東西一樣。
指針的聲明比普通變量的聲明多了一個一進制運算符 “*”。運算符 “*” 是間接尋址或者間接引用運算符
總結如下:
3.1.指針也是一種資料類型,也占用記憶體空間
1) 指針是用來幹嘛?
=>指針是用來存放位址的, 這個位址(p=&a)可以指向"int"型記憶體空間
例如定義:int a;//我們知道a是用來存儲整型資料的
例如再定義int *p; //那麼,指針也是一種資料類型,也可以用來定義變量
2)指針本身也有位址,也占用記憶體空間
=>指針定義時(int *p)不占用記憶體空間,當其指派(p=&a)時配置設定記憶體空間
3.2.一級指針: p 和 *p差別
"p"操作:
其實就是直接取出它記憶體空間裡面值(隻不過指針變量p存儲空間存放的是一個位址);
"*p"操作:
第一步,p操作,先去取出p存儲空間裡面的位址(p存儲的是一個位址);
第二步,*P操作,再把這塊位址裡面值取出來;
3.3.二級指針: p2 和 *p2 和 **p2操作順序
第一步: p2, p2操作,先取出p2記憶體空間裡面值,得到的這個值是一級指針的位址;
第二步: *p2, 再*p2操作, 取出一級指針記憶體空間裡面的值(一級指針記憶體空間裡面的值還是個位址,例如變量a位址);
第三步:**p2, 再**p2操作, 得到變量a的值;
#include "iostream"using namespace std;void main(){ int a = 100; int *p = &a; int **p2 = &p; //int ***p3 = &p2; //1.取值, 列印 printf("取值, 列印:%d, %d, %d\n", a, *p, **p2); //2.取位址, 列印 =>指針也是有位址的 printf("取位址, 列印:&a=%#x, &p1=%#x, &p2=%#x\n",&a, &p, &p2); //3.列印位址,對比 //=>p 和 &a列印都是同樣位址,因為p是用來存放a的位址 printf("列印位址,對比:p=%#x, &a=%#x\n", p, &a); //p2 和 &p列印都是同樣位址,因為p2用來存儲&p位址 //=>*p2 和 &a列印都是同樣位址,因為*p2取就是p存儲單元裡面值(即使a位址) printf("列印位址,對比:p2=%#x, &p=%#x ,*p2=%#x, &a=%#x\n", p2, &p, *p2, &a); system("pause"); return;}
最後輸出結果:
推薦閱讀:
專輯|C++專輯
專輯|Camera專業知識
專輯|攝像頭行業動态
專輯|程式人生