陳浩師兄03年的一篇博客《用C寫有面向對象特色的程序》描述了用C語言來實現相似C++類繼承的方法,這樣方法的核心要點就是結構體的強制類型轉換,讓我來簡單分析分析C語言中的結構體強制類型轉換,仍是用陳浩師兄原博的結構體來舉例吧。兩個結構體以下:安全
/* 雙向鏈表 (相似於父類)*/ typedef struct hLinks{ struct hLinks *bwLink; struct hLinks *fwLink; } hLinks;
/* * 一個使用雙向鏈表的結構 * (相似於子類) */ typedef struct hEnt{ hLinks links; int hData; char key[10]; } hEnt;
首先,咱們要搞清楚的一點是:C語言中的結構體並不能直接進行強制類型轉換,只有結構體的指針能夠進行強制類型轉換。所以你能夠在原博中看到在函數調用的時候有一些比較彆扭的參數形式,咱們來看看。函數
/* * 打印 (相似於子類重載父類的成員函數) */ PrintLink( hLinks *h ) { hEnt *p ; for( p = ( hEnt* ) h->fwLink; /* <-----------把hLink再轉回來 */ p != ( hEnt* ) h; p = ( hEnt* )( (hLinks*)p )->fwLink ) { printf("hData=[%d], key=[%s]/n", p->hData, p->key); } }
PrintLink函數的參數是一個hLinks類型的指針,所以在調用PrintLink時傳入參數也應該是hLinks類型的指針,若是咱們定義的時候用下面這樣的形式。spa
hLinks head;
那麼在調用函數的時候就必須把它轉換成hLinks指針,因而先取地址在強制類型轉換。.net
PrintLink( (hLinks *) &head );
這樣看起來確實是很彆扭,若是咱們在聲明結構體的時候這樣作的話就能夠避免這麼難看的傳遞形式。指針
typedef hLinks *PtrhLinks;
話說回來,結構體指針的強制類型轉換問題在這裏面始終存在。PrintLink中就出現了這樣的狀況,那麼在將hLinks指針轉換爲hEnt類型指針時有兩個問題:code
首先,結構體是儲存在一塊連續內存中的,計算機只關心的是結構體的大小和操做方式,結構體大小是定義的時候決定的(要進行對齊),而結構體的操做確實和結構體中的成員類型有關的。指針表示的是內存地址,那麼在強制類型轉換以後,計算機便以轉換後的結構體來看待這個地址內存中的內容。好比兩個結構體的內存結構以下:對象
hLinks hEntblog
*bwLink | *bwLink |
*fwLink | *fwLink |
——(未定義) | hData |
——(未定義) | key[10] |
能夠看出,在前兩個內存單元中兩個結構體存儲的內容是相同的,固然無論相不相同計算機是無論的,當hLinks類型轉換成hEnt類型時,計算機就將原結構體看作是hEnt類型的。轉換後的hEnt類型結構體的前面兩個內存單元的內容就是hLinks中的前兩個單元內容,而hEnt的後兩個內存單元中的內容取得是hLinks後的兩個單元(這兩個單元不是hLinks類型的成員,而是別的內容,全部若是轉換後的hEnt要訪問hData和key的話是不安全的!)。繼承
總之一句話,在轉換以後,計算機就按照轉換後的結構體的組成結構來解釋那麼一段內存中存儲的數據!!內存