[英]Why this redefinition of sizeof works
我將sizeof重新定義為:
#undef sizeof
#define sizeof(type) ((char*)((type*)(0) + 1) - (char*)((type*)(0)))
為此,定義中的2'0'必須是內存中的相同實體,換句話說,需要具有相同的地址。 是否始終保證這一點,還是依賴於編譯器/體系結構/運行時?
這里的0
不是對象-它是一個地址。 因此,您提出的問題是一個不合邏輯的問題。
您認為零是需要存儲在某處的離散數據。 它們不是..它們被轉換為指向內存位置零的指針。
當您增加一個類型的指針時,它實際上會增加它所指向的類型的大小。 這就是C數組算術的工作方式。
實際上,某種類型的空指針總是指向內存中的同一位置(尤其是當您以上述方式構造時),這僅僅是因為任何其他實現都是毫無意義的。
但是 ,該標准實際上不能對此提供很多保證:
這留下了很多余地。 假定具有兩個不同區域的內存模型。 每個區域可以具有一個空指針區域(例如前128個字節)。 很容易看出,即使在這種奇怪的情況下,有關空指針的基本假設確實可以成立! 好吧,給定一個合適的編譯器進行奇怪的null測試...
因此,關於指針,我們還了解什么...
首先,您要增加一個指針
“一個操作數應為指向完整對象類型的指針,另一個操作數應為整數類型。(遞增等於加1。)” [6.5.6§2]
然后是指針的區別
“兩個操作數都是指向兼容的完整對象類型的合格或不合格版本的指針” [6.5.6§3]
好的,它們是(假設類型是完整的對象類型)。 但是語義呢?
“出於這些運算符的目的,指向不是數組元素的對象的指針與指向長度為1且對象類型為其元素類型的數組的第一個元素的指針的行為相同。” [6.5.6§7]
這實際上是一個問題:空指針不必指向實際對象! (否則,您可以安全地取消引用它...)因此,將其遞增或從另一個指針中減去它是UB!
結論: 0
不指向對象,因此您的問題的答案為否。
嚴格符合標准的編譯器可能會拒絕這樣做,或者返回一些廢話。 在“典型”機器和指針上具有相同的大小,將整數強制轉換為指針只會采用該位模式,並將其視為指針。 在某些機器中,單詞包含額外的數據(可能是類型,允許位)。 某些對象可能禁止使用某些地址(即,任何地址都不能具有地址0),依此類推。 雖然可以保證sizeof(char) == 1
,但是在例如Crays上,字符實際上是32位。
此外,C標准保證,根本不會評估sizeof(expression)
,只取其類型即可。 即,^ sizeof(x ++) doesn't increment
x`。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.