[英]Narrowing conversions in C++11: what is the “actual value after conversion”?
以下代碼在C ++ 11中合法嗎?
int16_t x {0xaabb};
int64_t xxxx {0xaaaabbbbccccdddd};
該代碼來自“ The C ++ Programming Language”第4版(第150頁)。
眾所周知,列表初始化不支持縮小轉換,並且在標准的縮小轉換定義中,我們有:
縮小轉換是隱式轉換
— [...]
—從整數類型或無作用域枚舉類型到不能表示原始類型的所有值的整數類型,除非源是常量表達式,並且轉換后的實際值將適合目標類型並產生原始值當轉換回原始類型時。
通過對照示例代碼縮小轉換范圍的規則,我證明示例代碼是非法的,因為0xaabb
和0xaaaabbbbccccdddd
不能分別用int16_t
和int64_t
表示。 那是對的嗎?
但是我不太理解這樣的措辭:“除非源是一個常量表達式,並且轉換后的實際值將適合目標類型,並且轉換回原始類型時將產生原始值”。 我想知道在什么情況下轉換后的實際值不能適合目標類型 。 由於整數類型之間的轉換始終有效(盡管實現是在目標類型被簽名且源值不能在目標類型中表示的情況下定義的,但無論如何它都不是未定義的行為),因此“轉換后是否適合目標類型”? 從這個角度來看,我開始質疑我對示例代碼是否縮小轉換的判斷。 如果是這樣,為什么標准會在某種情況下總是存在某些事實? 為什么不說“除非源是一個常量表達式,並且轉換后的實際值在轉換回原始類型時將產生原始值,否則”?
有人可以幫我澄清一下嗎? 謝謝!
這是標准中的缺陷,請參閱CWG第1449版 。 文字已更改為
從整數類型或無范圍枚舉類型到不能表示原始類型的所有值的整數類型,除非源是一個常量表達式,其整數提升后的值將適合目標類型
注意:問題的狀態DRWP表示正式而言,該標准尚未更改,並且可以說至少您的int64_t
示例在C ++ 11中是合法的。 但是,編譯器已經實現了新規則,因為這已經是原始措辭的預期含義。
讓我們看一下如何將值轉換為有符號整數:
4.7 / 3如果目標類型是帶符號的,則該值可以用目標類型(和位域寬度)表示,則保持不變; 否則, 該值是實現定義的 。
因此,這些轉換提供了實現定義的值。 一個明智的實現將定義轉換,以為該位模式提供相應的負值,該負值確實適合目標類型。
所以問題是,轉換回文字的類型是否保留值? 這取決於文字類型的實現定義的大小。 如果int
恰好有16位,則第一個將保留該值,但是如果int
具有16位,則第一個將保留該值(在這種情況下, 0xaabb
進行簽名,並且轉換將給出負值)。 同樣,如果int
恰好有64位,或者int
較小且long long
恰好有64位,則第二個將保留該值。
結論:這取決於。 在具有32位int
和64位long long
的典型當前平台上,第一個會縮小,而第二個不會縮小。 GCC同意,並針對第一個帶有-pedantic
的用戶發出警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.