2014-02-25 59 views
2

我重新定義的sizeof爲:爲什麼這個重新定義的sizeof作品

#undef sizeof 
#define sizeof(type) ((char*)((type*)(0) + 1) - (char*)((type*)(0))) 

對於這項工作,在定義2「0」必須是同一個實體在內存中,或者換句話說,需要有相同的地址。這是總是保證,還是編譯器/體系結構/運行時間相關?

+2

我不明白爲什麼你感到吃驚的是這個工程。你似乎認爲'0!= 0'是可能的。 –

+0

減法是必要的,所以我們正在處理一個指針差異(定義值)與一個原始指針(未定義的實際值) –

+1

這些'0' **是地址。 – alk

回答

1

0這裏不是一個對象 - 它是一個地址。所以你問的問題是一個不太可靠的問題。

1

你在考慮零是需要存儲在某個地方的謹慎數據。他們不是......他們被當作指向內存位置零的指針。

當你將一個指針增加到一個類型時,它實際上會增加它指向的類型的大小。這是C數組運算的工作原理。

0

一個嚴格符合標準的編譯器可能會拒絕這個,或者返回一些廢話。在「典型」的機器和指針具有相同的大小,並將一個整數轉換爲一個指針只需要該位模式,並將其視爲一個指針。有些機器中的單詞包含額外的數據(類型也許是權限位)。某些地址可能被禁止用於某些對象(即沒有地址可以有地址0)等等。雖然可以保證sizeof(char) == 1,例如, Crays的字符實際上是32位。

此外,C標準保證sizeof(expression)中的expresison爲而非評估完全,只是它的類型被採用。即,sizeof(x ++)doesn't increment x`。

+0

根據[本手冊](http://docs.cray.com/books/004-2179-001/html-004-2179-001/rvc5mrwh.html),Cray'char'實際上是8位。儘管技術上允許使用該標準,但由於內存以字符計數,32位字符將成爲C中的一個巨大問題。 – user4815162342

1

在實踐中,某些類型的空指針總是指向內存中(的構造相同的方式尤其是當你做如上)相同的位置,只是因爲任何其他的實現將是毫無意義的。

然而,該標準實際上並不保證了很多關於這一點:

  • 「 [...]是保證比較不等於一個指向任何對象或函數」 6.3.2.3§3
  • 「[...]任何兩個空指針應比較相等。」 6.3.2.3§4

這留下了很多的李路。假設一個具有兩個獨特區域的記憶模型。每個區域可以有一個空指針區域(比如前128個字節)。很容易看出,即使在那個奇怪的情況下,關於空指針的基本假設確實可以成立!好吧,給定一個合適的編譯器,使怪異的空測試...

那麼,做什麼別的,我們知道一般的指針...

你所要做的是第一,增加一個指針

「一個操作數應是指向一個完整的對象類型和其他應具有整數類型。(增加等效於將1)」 [6.5。6§2]

然後指針差

「兩個操作數都指向兼容完全對象類型的合格或不合格的版本」 6.5.6§3]

好的,他們是(好吧,假設type是一個完整的對象類型)。但是語義呢?

「對於這些操作符的目的,一個指針到一個對象,它是不是一個數組的元素的行爲相同的指針長度的一個的陣列與作爲對象的類型的所述第一元件其元素類型「。 [6.5.6§7]

這實際上有點問題:空指針不需要指向實際的對象! (否則你可以安全地解除引用...)因此,增加它或從另一個指針中減去它就是UB!

總之:0不指向一個對象,因此回答你的問題是第

+0

事實上,這是UB,儘管[鏈接](http://en.wikipedia.org/wiki/Undefined_behavior)或UB的一些解釋會很好。 –

相關問題