詳細解析:如何確定域在結構中的位元組偏移的 C語言的程式碼的實現
ANSI C 在 <stddef.h> 中定義了 offsetof() 巨集, 用 offsetof(struct s, f) 可以計算出域 f 在結構 s 中的偏移量。如果出於某種原因, 你需要自己實現這個功能, 可以使用下邊這樣的程式碼:
#define offsetof(type,f) ( (size_t) ( (char*)&((type*)0)->f - (char*)(type*)0) )
這種實現不是 100% 的可移植; 某些編譯器可能會合法地拒絕接受。
注:上述文字來源於書籍《你必須知道的495個C語言問題》。
上述程式碼對於大神來說可能一眼或者兩眼就能看懂,但是對於C語言還是像我一樣還在懵逼狀態的小白來說就同樣懵逼,精闢的程式碼沒有解釋,讓小白們體會不到C語言的強大之處,遍尋(稍微翻了翻)Internet無果後,我決定自己用自己的理解來解釋一下,還是不理解的下方評論留言。
理清問題,要用拆的思想,由區域性到整體,由內而外。(裝逼的方法論。。。。)
首先這句話的意思是將
( (sie_t) ( (char*)&((type*)0)->f - (char*)(type*)0) )
用巨集定義#define功能實現用
offsetof(type,f)
來代替。 也就是我們呼叫 offsetof(type, f) 就是使用了 ((size_t) ((char *)&((type *)0)->f - (char *)(type *)0)) 這句精妙的語句。實現的功能就是上文所說的可以計算出域 f 在結構 s 中的偏移量(這裡偏移量的單位是位元組
1. (type*)0 //將0強制轉換為指向type型結構體的指標,即假裝地址0處有一個type的結構
2. (char*)(type*)0) //將1.處的結構體指標強制轉換成字元型指標,這樣做的目的是為了使指標(也是一種地址)做減法時得出的偏移量的單位是位元組型
3. ((type*)0)->f //這段程式碼的結果是得到地址在0處的type結構體的成員f的值
4. &((type*)0)->f //在3.的基礎上加上了取地址符&,得到的是地址在0處的type結構體的成員f的值的地址
5. (char*)&((type*)0)->f //在4.的基礎上加上(char*) ,目的同2.處
6. (char*)&((type*)0)->f - (char*)(type*)0) // 這裡其實是上面的5. -2.(結構體成員地址 - 結構體基地址),
//得到的就是我們所求的偏移量(以位元組為單位)
7. 在6. 整體上又加了強制型別轉換(size_t),目的是為了使結果為無符號整數。
補充一下size_t的來源。
百度百科:
size_t是標準C庫中定義的,應為unsigned int,在64位系統中為 long unsigned int。