C 指標解惑

2021-06-10 12:15:53 字數 2734 閱讀 3212

之前在使用指標的時候,常常對指標的型別感到困惑,既然所有的指標都只佔4個位元組,那麼他所對應的指標型別在指標轉化過程中有什麼作用呢。最近,終於弄懂了他們的關係,相關說明如下:
1.前提首先定義了乙個zooanimal類如下:

class zooanimal;
2.說明定義如下三個指標:

zooanimal *px;

int *pi;

array*pta;

以記憶體需求的觀點來說,沒什麼不同,他們三個都需要有足夠的記憶體來放置乙個機器位址(32位機器上是4位元組)。「指向不同型別之各指標」間的差異,既不在於其指標的表示不同,也不在其內容不同,而是在其所定址出來的object型別不同。也就是說,「指標型別」會教導編譯器如何解釋某個特定位址中的記憶體及其大小:

1.乙個指向位址1000的整數指標,在32位機器上,將涵蓋位址空間1000--1003.

2.如果string是傳統的8-bytes(包括乙個 4-bytes的字元指標和乙個用來表示字串長度的整數),那麼乙個zooanimal指標將橫跨位址空間1000--1015。如下圖所示:

乙個指向位址1000而型別為void*的指標,將涵蓋怎樣的位址空間呢?是的,我們不知道!這就是為什麼乙個,型別為void *的指標只能夠含有乙個位址,而不能夠通過它操作所指之object的緣故。

所以,轉型(cast)其實是一種編譯器指令,大部分情況下它並不改變乙個指標所含的真正位址,它只影響「被指出之記憶體的大小和其內容」的解釋方式。

3.加上多型之後

現在,讓我們定義乙個bear,作為一種zooanimal。當然,經由"public 繼承"可以完成這件任務:

class bear:public zooanimal;

dances dances_known;

int cell_block;

};bear b("yogi");

bear *pb=&b;

bear &rb=*pb;

b,pb,rb 會有怎樣的記憶體需求呢?不管是pointer或reference都只需要乙個word的空間(在32位機器上是4-bytes)。bear object需要24bytes,也就是zooanimal的16bytes加上bear所帶來的8bytes。下圖展示了可能的記憶體布局:

好,假設我們的bear object 放在位址1000處,乙個bear指標和乙個zooanimal指標有什麼不同?

bear b;

zooanimal *pz=&bl;

bear *pb=&b;

它們每個都指向bear object 的第乙個byte。其間的差別是,pb所涵蓋的位址包含整個bear object,而pz所涵蓋的位址只包含bear object中的zooanimal subobject。

除了zooanimal subobject 中出現的members,你不能夠實用pz來直接處理bear的任何menbers。唯一例外是通過virtual機制:

//不合法:cell_back不是zooanimal的乙個member,雖然我們知道pz當前指向乙個 bear object。

pz->cell_back;

//ok:經過乙個明白的downcast操作就沒有問題 !

((bear *)pz)->cell_block;

//下面這樣更好,但是它是乙個run-time operation (成本較高)

if(bear *pb2=dynamic_cast(pz))

pb2->cell_block;

//ok,因為cell_block是bear 的乙個member。

pb->cell_block;

當我們寫:

pz->rotate();
時,pz的型別將在編譯時期決定以下兩點:

1.固定的可用介面。也就是說,pz只能夠呼叫zooanimal的public 介面。

2.該介面的access level(例如rotate()是zooanimal的乙個public member)。

在每乙個執行點,pz所指的object型別可用決定rotate()所呼叫的實體,型別資訊的封裝並不是維護於pz之中,而是維護於link之中,此link存在於「object 的vptr」和「vptr 所指之virtual table之間」

另外,c++的多型就是通過指標和引用實現的,例如:

bear b;

zooanimal za=b;

//呼叫zooanimal::rotate()

za.rotate();

在以上**中,使用bear型別物件初始化zooanimal物件,必然會對bear型別物件進行裁剪,只是保留跟zooanimal有關的資訊。所以za.rotate()必然是呼叫zooanimal中的rotate(),所以多型不能夠在"直接訪問objects"上發揮作用。

《深度探索c++物件模型》

C 指標使用方法解惑

在下列函式宣告中,為什麼要同時使用 和 符號?以及什麼場合使用這種宣告方式?void func1 myclass pbuildingelement 論壇中經常有人問到這樣的問題。本文試圖通過一些實際的指標使用經驗來解釋這個問題。仔 細看一下這種宣告方式,確實有點讓人迷惑。在某種意義上,和 是意思相對...

C語言指標問題快速解惑

1 int a 3 int p a 把陣列名賦值給指標表示將陣列的首元素的位址賦予此指標。2 int a 3 int p a 0 a 0 是a陣列的首元素,而 則是取位址運算子,所以 a 0 取得的同樣是a陣列的首元素的位址,因此這段 的含義和 段是一致的。3 char c1 hello char ...

C 指標使用方法解惑

在下列函式宣告中,為什麼要同時使用 和 符號?以及什麼場合使用這種宣告方式?void func1 myclass pbuildingelement 論壇中經常有人問到這樣的問題。本文試圖通過一些實際的指標使用經驗來解釋這個問題。仔細看一下這種宣告方式,確實有點讓人迷惑。在某種意義上,和 是意思相對的...