由於整數下溢,while循環是否包含未定義的行爲?
首先這是一個Boolean Conversion:
積分,浮點,無作用域枚舉,指針,指針到成員類型的prvalue可以轉換爲bool
類型的prvalue。
值爲零(用於積分,浮點和非範圍枚舉)以及空指針和空指針至成員值變爲false
。所有其他值變爲true
。
所以不會有整數下溢如果i
正確初始化,將達到0U
和將被強制轉換爲false
值。
那麼編譯器有效地在這裏做的是:while(static_cast<bool>(i--))
難道編譯器都正確的假設,while循環總是true
因爲這一點,帶着無盡的循環結束了?
這不是無限循環的關鍵原因是postfix decrement operator返回減量變量的值。它的定義爲T operator--(T&, int)
正如之前討論的那樣,編譯器將評估該值是否爲0U
,作爲轉換爲bool
的一部分。
什麼編譯器有效地在這裏做的是:while(0 != operator--(i, 1))
在你更新你舉這個代碼作爲你的問題的一個動機:
void fn(void)
{
/* write something after this comment so that the program output is 10 */
int a[1] = {0};
int j = 0;
while(a[j] != 5) ++j; /* Search stack until you find 5 */
a[j] = 10; /* Overwrite it with 10 */
/* write something before this comment */
}
經檢查,這整個程序已經未定義的行爲有隻有a
的1個元素,並且它已初始化爲0.因此,對於除0
以外的任何索引,a[j]
都在關注數組的末尾。這將持續到找到5
,或者直到操作系統錯誤,因爲程序已從受保護的內存中讀取。這與您的循環條件不同,後綴遞減運算符返回值爲0時將退出,因此不能假定這始終爲true
,或者循環將無限持續。
如果i
是signed int
?
上述兩種轉換均內置於C++。它們都是爲所有整數類型定義的,有符號和無符號。所以最終這擴展到:
while(static_cast<bool>(operator--(i, 1)))
它是否包含與數組訪問有關的陷阱?
同樣,這調用內置的操作中,subscript operator:T& operator[](T*, std::ptrdiff_t)
所以a[i]
是調用operator(a, static_cast<ptrdiff_t>(i))
相當於所以顯而易見的後續問題是什麼是ptrdiff_t
?它是一個實現定義的整數,但是因爲標準的每個實現都負責定義這種類型的轉換,所以i
將正確轉換。
那麼,這是**不是**無限循環。 –
當你運行它時發生了什麼? –
沒問題,因爲'while(0)'是錯誤的,之後你不關心'i'的值 – MrTux