[英]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
實際上並沒有嘗試加載ptr
或ptr->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.