我看了this很好太寬了問題,遇到一些UB我以前都不知道。有沒有規則可以發現UB?
UB我不時看到的主要原因是在兩個序列點之間改變兩次變量。諸如:x = x++
或z = y++ + ++y;
。讀取在兩個序列點之間兩次更改變量是UB幫助我瞭解這些情況下的根本原因。
但是,像負位移位這樣的事情呢? (int x = 8 << -1
)有沒有一個規則可以解釋或者我應該記住這是一個獨特的UB可能性?
我看了here和部分整數溢出我發現帶負片的位移是寫的,但我不明白他們爲什麼相關。當int
被移位太多時,會引起溢出,但IMO發生負移位僅僅是UB,並且問題不在於「超出邊緣」的位...
也看了這裏,沒有回答我的問題:
對每個操作數執行整數升級。結果的類型是提升的左操作數的類型。如果右操作數的值爲負或者大於或等於提升的左操作數的寬度,則行爲未定義。
所以我的問題是:
- 具體而言,位移位與底片考慮整數溢出,如果是這樣,爲什麼?
- 如果不是,它是更大現象的一部分嗎?
- 是否存在(其他)不能歸類於一個基本原因下的獨特個案?
負移位未定義,移位過長(對於N位整數類型移位N位或更多位)也是如此。該標準如此說。你必須知道它是這樣說的。是的,有很多情況,將它們分組會很棘手。 C11標準的附錄J.2在第557-571頁上記錄了未定義的行爲(每個結束頁面只有幾行,因此它多於14頁)。定期閱讀以瞭解未定義的內容。沒有;我還沒有記住它。 –
@JonathanLeffler這是一個令人印象深刻的名單,thx!儘管我希望有更容易記住的東西:) – CIsForCookies
回答你的部分 - *我希望更容易記住的東西*我的一般經驗法則是 - 任何似乎改變不同實現(目標,平臺等)行爲的東西是一個紅旗「點」UB。然後我確認清單。這很有意義,因爲標準是在抽象機器上定義的,而不是任何實現。因此觸摸實現的方面必須保持未定義。警惕實施定義的行爲。 –