指標系列 認識指標

2021-07-03 08:35:11 字數 2861 閱讀 5327

指標在c++學習中一直是難點和重點,由於在專案中指標應用比較靈活,所以指標所引發的問題比較多,最近針對指標進行重點學習。有人說,掌握指標,也就掌握c語言的精髓。c++中當然也有指標,同時還包括繼承、多型等等。

沒有記憶體,就沒有指標,在理解指標的開始階段,先重點講解記憶體五區。

如上圖所示:一般下理解記憶體分為棧、堆、常量區、**區、全域性區。

棧:程式中區域性變數、引數包括形參、陣列、指標存放在棧中,編譯器在函式呼叫結束後,自動釋放,所以注意指標的指向。

堆:程式設計師手工申請的記憶體(molloc,new),一般堆記憶體比棧記憶體大,在大資料處理中,可以利用堆,進行資料儲存、計算。

常量區:包括常量、字串常量,指標指向此區,不能修改常量值

**區:存放函式體的二進位制**。

全域性區:全域性變數和靜態變數儲存放在一塊,在程式結束後自動釋放。

int a = 0;//a全域性初始化區

char * p ;//全域性未初始化區

int main()

堆和棧在程式到底有什麼不同,當然從表面上可以看到兩者因為申請方式不一樣,可以清晰知道兩者的區別。那在記憶體中具體的不同有哪些。

1. 管理方式不同

棧是編譯器自動管理,堆需要我們手工建立,手工釋放。在程式中,一般通過記憶體的指標進行釋放,所以指向堆的指標指向千萬不能變化。要有乙個指標儲存申請記憶體的首位址。

空間大小不同

一般在32位作業系統下,棧的記憶體一般都是一定的空間的大小的,在vc6下面預設的空間大小是1m,而堆的大小可以達到4g空間,從這個角度上講堆記憶體幾乎沒有限制。

碎片問題

對於堆來講,因為經常new/delete操作,造成記憶體空間不連續,造成大量的記憶體碎片,使程式效率低下。棧就沒有這種問題。

生長方向

堆是向上生長,棧向下生長。意味在程式中申請棧和堆的記憶體時,記憶體位址變化方向不一樣。棧中變數申請越往後,位址越小。

分配方式

堆是動態分配,沒有靜態分配的堆。棧有2中分配方式,靜態分配就是常見的區域性變數宣告。動態分配有alloca分配,系統自動**。

分配效率

棧由機器系統提供的資料結構,計算機底層對棧支援:專門的暫存器存放棧的位址,有壓棧出棧指令執行,決定棧的效率較高。堆是由c++函式庫提供,機制比較複雜,如果沒有足夠記憶體空間(碎片過多),極有可能呼叫系統功能去增加程式資料段的記憶體空間,然後再返回。顯然堆的效率比較低下。

在程式中大量使用new/delete,容易造成大量記憶體碎片,效率低下。棧在程式中應用最廣泛,就是函式呼叫也是通過棧完成,函式呼叫過程的引數,返回位址和區域性變數採用棧的方式存放。

沒有記憶體,就沒有指標,這句話充分說明指標的本質和作用。在系統中如果指標指向的記憶體空間沒有記憶體,肯定報錯,另一方面,利用指標去修改唯讀記憶體的內容,也是報錯的。如果理解指標,必須從四個方面理解:1、指標型別;2、指標指向變數的型別;3、指標的值或者說指向記憶體空間位址;4、指標本身佔據的記憶體區。

首先指標是變數,是一種特殊的變數,它裡面儲存的數值被解釋為記憶體裡的乙個位址,在指標變數加*後,就可以獲取或操作指向記憶體空間的值。這樣通過指標操作記憶體中資料便很方便。

下面舉例說明下

int* ptr;//指標的型別是:int*

char* ptr;//指標的型別是:char*

int ** ptr;//指標的型別是:int**

int (*ptr);//指標的型別是:(*)

int *(*ptr);//指標的型別是:*(*)

找出指標的型別很簡單,關鍵是指標指向的型別。當你同過指標來訪問指標所指向的記憶體區時,指標指向的型別決定了編譯器吧記憶體裡內容當做什麼看待。從語法看看,只需要把指標宣告語句中*,去掉,便得知。

int (*ptr)[3]//指標指向型別為int()[3],意味著*(ptr+1)時,記憶體跳轉大小是3

*sizeof(int),而不是sizeof(int)了,這是指向陣列的指標。

指標的型別和指標指向的型別很不一樣,我們常常關心指標指向的型別。

指標的值是指指標本身儲存的數值,由於在32位程式中,指標的值就是個32位整數,所以指標佔據4個位元組。我們說指標的值是xx,就是指標指向了以xx為首位址的一片記憶體區域。

指標指向的值就是指向記憶體空間中的值,也可以是函式指標奧。

在c/c++中關鍵字const用來定義乙個唯讀的變數或者物件,有如下優點

(1)便於型別檢查,如函式的函式 fun(const int a) a的值不允許變,這樣便於保護實參。

(2)功能類似與巨集定義,方便引數的修改和調整。如 const int max = 100;

(3)節省空間,如果再定義a = max,b=max。。。就不用在為max分配空間了,而用巨集定義的話就一直進行巨集替換並為變數分配空間

(4)為函式過載提供參考

首先一定要明白哪種定義方式是常量指標,哪種是指標常量,這裡可以記住三句話加深記憶:

int a =3;

int b = 1;

int c = 2;

intconst *p1 = &b;//const 在前,定義為常量指標

int *const p2 = &c;//*在前,定義為指標常量

p1 = &a是正確的,但 *p1 = a是錯誤的。

指標常量p2:指向的位址不可以重新賦值,但內容可以改變,必須初始化,位址跟隨一生。

p2= &a是錯誤的,而*p2 = a 是正確的。

Delphi指標認識

大家都認為,c語言之所以強大,以及其自由性,很大部分體現在其靈活的指標運用上。因此,說指標是c語言的靈魂,一點都不為過。同時,這種說法也讓很多人 產生誤解,似乎只有c語言的指標才能算指標。basic不支援指標,在此不論。其實,pascal語言本身也是支援指標的。從最初的pascal發展至今的obje...

指標初步認識

int a 10 p p a 0 p a 形式 含義 p p先加1,再取p的值 p p指向的物件加1 有 p 和 p 先取 p的值,再p 指標間可以相減,不可相加,相加無實際意義。說明 是變址運算子,即a i a i 使用指標指向陣列元素注意事項 1.可以通過改變指標變數的值指向不同元素 2.不用p...

delphi 指標 認識

delphi 指標分為型別指標和無型別指標 型別指標分為pchar pinteger pstring等。無型別指標pointer。ppchar pp.為指標的指標 和addr一樣,為獲取變數存放的位址 為指標指向的內容。變數,addr 變數 指標 var p pchar 這樣定義 p為型別指標 pc...