2010-04-02 45 views
5

linux的stddef.h定義offsetof()爲:爲什麼要減去offsetof()中的空指針?

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 

而在offsetof()http://en.wikipedia.org/wiki/Offsetof)維基百科的文章將其定義爲:

#define offsetof(st, m) \ 
    ((size_t) ((char *)&((st *)(0))->m - (char *)0)) 

爲什麼在維基百科版本減去(char *)0?有沒有什麼情況下,這實際上會有所作爲?

+0

不應該使用/研究可能調用未定義行爲的代碼,如上所述。一個實現可以使用這種不正當的黑客,因爲他們知道什麼樣的未定義的行爲祕密工作。但是「祕密行事」是完全不可移植的。 – CTMacUser 2013-10-15 06:21:13

回答

6

的第一版本的指針轉換爲具有流延,這是不可移植的整數。

第二個版本在更廣泛的編譯器中更具可移植性,因爲它依靠編譯器的指針算法來獲得整型結果而不是類型轉換。

順便說一句,我是編輯器,它將原始代碼添加到Wiki條目中,這是Linux的形式。後來的編輯將它改爲更便攜的版本。

+0

感謝您的回覆。後續問題「(size_t)((char *)0)是否未評估爲0?」發佈在http://stackoverflow.com/questions/2581522/does-size-tchar-0-ever-not-evaluate-to-0 – 2010-04-05 22:22:42

+0

有趣的 - 但是第二個表達式真的更便攜,因爲空指針上的指針算術未定義? – 2010-04-05 23:00:36

+1

它在更多CPU上工作的意義上更具可移植性。未定義(按標準)並不意味着它不適用於某些特定的體系結構。 – 2010-04-11 01:02:08

4

該標準不要求NULL指針評估位模式0,但可以評估爲特定於平臺的值。

做減法保證當轉換爲一個整數值,NULL是0

+2

這不是原因;除'0'以外的任何合理常數也可以使用。請參閱下面的答案。 – 2010-04-02 20:19:16