簡體   English   中英

使用指針訪問結構元素

[英]Accessing structure elements using pointers

當下面的程序沒有崩潰時,我感到很驚訝。

typedef struct _x {
  int a;
  char b;
  int c;
} x;

main() {
  x *ptr = 0;
  char *d = &ptr->b;
}

根據我的理解, ->運算符優先於&運算符。 所以當我們嘗試取消引用NULL指針tr時,我希望程序在下面的語句中崩潰。

char *d = &ptr->b; 

但語句&ptr->b計算為有效地址。 有人可以解釋一下我錯了嗎?

你的期望是沒有根據的。 取消引用空指針時,C程序不一定“崩潰”。 當您嘗試執行類似的操作時,C程序會出現所謂的未定義行為 未定義的行為可以通過許多不同的方式表現出來。 它可能導致崩潰。 或者它可以產生甚至類似於“工作”程序的東西。 后者顯然是你的情況。

但無論如何,你的程序的行為是不確定的。 不,它不會產生一個“有效地址”,因為你似乎錯誤地相信。 對應於內存中沒有對象存在的位置的數字地址無效(當然,空指針值除外)。

您的代碼沒有崩潰的原因是您實際上沒有取消引用指針。 注意表達式

&ptr->b

實際上並沒有嘗試加載ptrptr->b的內容。 相反,它只是存儲它在內存中的位置。 你最終得到的是指向ptr指向的對象的b字段的指針。 這將是地址0之后的幾個字節,因此取消引用剛創建的指針將導致段錯誤。

&ptr->b == sizeof(int) ,表示_x.a (類型為int )之后_x內的b相對於地址*((x*)0)的偏移量。 偏移量為4 (典型值為32位架構)保存在d指針中。 您必須訪問d才能獲得seg-fault。

計算地址不需要訪問內存。 &ptr->b表示“給我ptr指向的結構的b字段的地址。” 這樣做不需要查看可能存儲在該存儲器位置的任何內容。

考慮索引數組而不是結構可能會有所幫助。 C將ptr[5]定義為等價於*(ptr + 5) ,這意味着&(ptr[5])&(*(ptr + 5)) 現在很容易看到&* “取消”並留下(ptr + 5) ,它只涉及指針增量,而不是來自內存的負載。

C使它略微混濁,因為它區分左值和右值。 也就是說,表達式的表達式在表達式的左側與右側的表達式區別對待。 給出像x = y;的陳述x = y; ,C編譯器將從y的地址加載一個值,並將其存儲在x的地址中。 這是區別: y被隱式解除引用,但x不是。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM