你正在尋找的規則是在§3。10/10(在C++ 11):
如果一個程序試圖通過其它一個glvalue比以下類型的 行爲理解過程音響定義中的一個來訪問對象 的存儲值: - 的動態型的對象,
- 動態類型的對象的CV-合格音響編版本,
- 類似於一個類型(德音響定義在4.4)的動態類型的對象,
- 是一種類型對應於動態型的對象, 的符號或無符號類型 - 一種類型,是有符號或對應的動態對象的類型 的CV-合格音響編版本無符號類型,
- 一個聚集或聯合類型包括其元件或非靜態 數據成員(包括,遞歸地,一個元件或子聚集 或含有聯合的非靜態數據成員)之間的上述類型的一個,
- 一種類型,是一個(可能cv-quali fi ed)基類動態類型的對象,
- char或unsignedchar類型。
對於未定義的 行爲有不同的類型(或動機)。
在鑄造int*
到float*
,然後 解引用它的情況下,很顯然,該標準不能定義 它,因爲會發生什麼取決於架構,並 的int
的價值。在另一方面,引用的段落 是完全錯誤的—使用memcpy
做轉換是 也是不確定的行爲,主要是由於同樣的原因。
一個動機未定義行爲的是 允許實現來定義它,以這樣的方式,使感 爲目標架構,如果這樣存在。這就是這樣的 一個案例。故意導致其失敗的編譯器是 有缺陷。當然,如果我們假設32位2的補碼 int
和32位IEEE float
,我們可以預計 ,int
的某些值對應於捕獲NaN,這將導致程序 失敗。這是行爲是 未定義的原因的一部分;讓這種事情發生。但是如果我們熟悉 的低層硬件細節, 吧應該按預期工作,提供編譯器可以看到 的投。 如果不是這樣,這是編譯器的QoI問題,並且應該避免編譯器針對這些類型的工作。
作爲暗示以上,該特定情況下,事實上,在所有 案件涉及式雙關(寫入的 一個成員的結合,並從另一個讀取,例如),不要造成 一個問題,該標準尚未找到足夠的措辭。出現此問題的原因通常是,編譯器允許 假定指向不同類型的指針( 字符類型除外)不是別名; int*
不能指向 與float*
相同的對象。並證明兩個指針 不能別名對優化很重要。一個編譯器, 中斷代碼的指針演員或聯合是清晰可見的 剛剛壞了,即使標準說它是未定義的行爲。 一個編譯器可以將所有看到的代碼都分解爲兩個指針 到不相關的類型,這是可以理解的,即使在 標準說明行爲已被很好地定義的情況下也是如此。
使用memcpy
通過使用兩個不同的 對象(它們不是別名)來避免此問題。它仍然遇到未定義的 行爲,因爲將int
的位模式設置爲 a float
,然後訪問浮動,沒有任何定義的 行爲。 (反之亦然。我知道至少有一臺機器,其中 複製的float
位爲int
可能導致 非法int
值)
在C++中,你應該看看在不同類型的鑄件標準章節5.4,安全派生指針3.7.4.3,static_cast 5.2.9,reinterpret_cast 5.2.10 ... –
偶然事件:昨天最新的STL [video](http://channel9.msdn.com/Series/C9-Lectures- Channel 9上的Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-Cpp-8-of-n)包含C++類型轉換中的段(包括對標準的引用) – TemplateRex