簡體   English   中英

ptrdiff_t太小了?

[英]ptrdiff_t too small?

我一直在想:是不是ptrdiff_t應該能夠舉辦任何兩個指針定義的區別? 當兩個指針太遠時怎么會失敗呢? (我沒有指出任何特定語言......我指的是所有具有此類型的語言。)

(例如,當你有32位指針時,用地址0xFFFFFFFF從字節指針中減去帶地址1的指針,它會溢出符號位...)

不它不是。

$ 5.7 [expr.add] (來自n3225 - C ++ 0x FCD)
當減去指向同一數組對象的元素的兩個指針時,結果是兩個數組元素的下標的差異。 結果的類型是實現定義的有符號整數類型; 此類型應與<cstddef>標頭(18.2)中定義為std::ptrdiff_t類型相同。 與任何其他算術溢出一樣,如果結果不適合所提供的空間,則行為未定義。 換句話說,如果表達式PQ分別指向數組對象的第i和第j個元素,則表達式(P)-(Q)具有值i − j條件是該值適合於std::ptrdiff_t類型的對象。 此外,如果表達式P指向數組對象的元素或者指向數組對象的最后一個元素,並且表達式Q指向同一數組對象的最后一個元素,則表達式((Q)+1)-(P)具有與((Q)-(P))+1-((P)-((Q)+1))的值,並且如果表達式P指向一個,則值為零數組對象的最后一個元素,即使表達式(Q)+1沒有指向數組對象的元素。 除非兩個指針指向同一個數組對象的元素,或者指向數組對象的最后一個元素,否則行為是未定義的。

請注意段落中出現undefined的次數。 另請注意,如果指針指向同一對象,則只能減去指針。

不,因為沒有“任何兩個指針”之間的區別。 您只能減去指向同一數組元素的指針(或指向剛好超過數組末尾的位置的指針)。

要添加更明確的標准引用, ISO 9899:1999 §J.2/1規定:

在以下情況下,行為未定義:

[...]

- 減去兩個指針的結果在ptrdiff_t(6.5.6)類型的對象中無法表示。

ptrdiff_t與指針類型的大小完全相同,只要溢出語義由編譯器定義,這樣任何差異仍然可以表示。 無法保證負ptrdiff_t意味着第二個指針位於內存中比第一個更低的地址,或ptrdiff_t根本沒有簽名。

對於固定大小的整數運算,上/下溢在數學上是明確定義的:

(1 - 0xFFFFFFFF) % (1<<32) =
(1 + -0xFFFFFFFF) % (1<<32) =
1 + (-0xFFFFFFFF % (1<<32)) = 2

正確的結果!

具體來說,上溢/下溢后的結果是正確整數的別名。 事實上,每個不可表示的整數都有一個可表示的整數別名(無法區分) - 在固定大小的整數中計數到無窮大,你會像模擬時鍾的表盤一樣重復自己,圓形和圓形。

N位整數表示模2 ^ N的任何實數。 在C中,模2 ^ N寫為%(1 << 32)。

我相信C保證上溢/下溢的數學正確性,但僅適用於無符號整數。 假設簽名在/溢出下永遠不會發生(為了優化)。

在實踐中,有符號整數是兩個補碼,這在加法或減法中沒有區別,因此對於有符號整數也保證正確的欠/溢出行為(盡管不是由C)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM