指標篇之六 指標與結構體,小心刻舟求劍

2021-06-19 14:47:34 字數 1911 閱讀 3606

指標與結構沒有指標與陣列的關係那麼複雜,卻也有一些需要注意的地方。例如:

typedef struct

mystruct;

mystruct ss=;  //宣告物件ss,三個成員初始化

mystruct *ptr=&ss;          //宣告指向物件ss的指標。指標指向的型別是mystruct

int *pint=(int*)&ss;           //宣告指向物件ss的另一指標。指向的型別和ptr不同

怎樣通過指標ptr訪問ss的成員變數?答:ptr->a; ptr->b;ptr->c;  那

是否可通過指標

pint直接

訪問ss

的成員變數呢?有人會這樣實現:

* pint;//

訪問成員

a*(pint +1);     

//訪問成員

b*(pint +2);//

訪問成員

c這裡通過手動偏移指標訪問結構體成員,效果和通過結構體指標訪問成員變數基本等價。結構體本質就是程式設計師和

c語言約定一段記憶體空間的長短,以及其中記憶體元素排列的安排

。但通過指標偏移訪問

struct

成員既不正規又有隱患,是一種繞過編譯器的「硬編譯」:結構體中成員位置或大小必須一成不變,一旦改變就與硬編碼的位址增量不匹配,比如在int a前加個int d,那後面所有成員的偏移都會發生變化,這時還以為*pint是訪問a,*(pint+1)訪問b麼?那就真應了一句成語——刻舟求劍。

即使成員變數大小位置永遠不改動,這種方式是否就沒問題呢?還是不行!因為還有記憶體對齊的問題。在記憶體中,編譯器按成員列表順序分別為每個struct成員變數分配記憶體,如果系統有記憶體邊界對齊的要求,編譯器會自動在不滿足對齊要求的成員前新增若干填充位元組,這導致成員變數間可能有多的空白位元組。如:

typedef struct

mystruct;

mystruct ss=;

char *pint=&ss

這時*pint

和*(pint+1)

可以訪問

ss的成員變數a和

b,但*( pint +2)

是否定能訪問到結構成員

c呢?不一定!因為c是

int型,

bc之間可能有編譯器插入的填充位元組,以保證

c的位元組對齊(見記憶體對齊),此時

*( pint +2)

訪問的可能是填充位元組(如下圖,假設

這也再一次說明了指標靈活與危險並存。所以指標訪問結構體成員還是老老實實用

」->」

號吧,即由編譯器根據結構體定義確定成員變數的偏移,以隔絕不同編譯器之間記憶體對齊的差別。但如此也並非萬無一失,以下情況仍要小心

1)如果存在不一致的結構體定義呢?比如給客戶開發功能庫,

api介面引數裡包含乙個結構體指標,如果某次更新庫時修改了

api標頭檔案裡這個結構體的定義,並重編譯了庫,但發給客戶時只提供了更新庫,而忘記提供修改過的標頭檔案,會發生什麼?

2)第三方開發者還可能使用不同的編譯器預設對齊選項,使得結構體在發行庫中與外部呼叫者那裡使用不同對齊方式,這也會導致同樣問題。 3

)手動偏移訪問結構體成員變數在

c語言中很少見,沒人會拋開

」->」

而費力不討好,但如果要手工編寫彙編函式且與

c介面存在結構體引數傳遞,這個問題就無法迴避:彙編裡訪問結構體成員,只能在彙編指令裡硬性指定偏移量。這時就要調整彙編中的偏移量值,使其和

c編譯器的結果保持吻合,否則

c和彙編的混合呼叫就會發生函式引數傳遞錯誤。而此時在c裡修改這種被彙編和c共享的結構體定義,是牽一發動全身,要特別小心。

2019 8 2 3 指標 引用 結構體 cin

指標也是c 資料型別的一種,它也有系統分配的記憶體位址,不過它的記憶體空間中存放著另乙個變數的記憶體位址。include using namespace std intmain output 0x7ffee797219c 0x7ffee797219c 0x7ffee7972190 可以看出,p存放的...

C Day4 指標和結構體

二 結構體 include using namespace std intmain 32位作業系統 64位作業系統 4位元組 所有型別int float double 8位元組 所有型別 int s int 0x1124 cout 指標的值 sconst既修飾指標又修飾常量。const int co...

指標系列六(指標與二維陣列)

指標與二維陣列 int array 4 5 printf sizeof int d n sizeof int printf array p n array printf array 1 p n array 1 上面程式證明 array 1,位址加了20,每乙個整形四個位元組,相當於跨越了五個位元組 ...