簡體   English   中英

什么是C ++中的不確定行為? 它與未定義的行為有什么不同?

[英]What is indeterminate behavior in C++ ? How is it different from undefined behavior?

C ++中不確定行為和未定義行為之間有什么區別? 此分類是否也適用於C代碼?

以下評論基於C標准ISO-9899 ,而不是C ++標准,但其含義基本相同(參見C標准的3.4和4節;另見C ++標准, ISO-14882,1.3節) ;后一個文檔沒有定義'未指定的值',但后來確實使用了該詞組,具有明顯的含義)。 官方標准文件不是免費的(事實上,它們很昂貴),但上面的鏈接是委員會頁面,並包括標准的免費“草稿”,您可以采取這些標准基本上等同於最終的標准文本。

這些術語描述了模糊的階梯。

所以,向下走......

大多數情況下,標准定義了在特定情況下應該發生的事情:如果你寫c=a+babint ,那么c就是它們的總和(以某些細節為模)。 當然,這是標准的要點。

實現定義的行為是標准列出在特定情況下允許發生的兩件或更多事情的地方; 它沒有規定哪一個是首選,但確實要求實現(解析C的實際編譯器)在備選方案之間作出選擇,同樣地做同樣的事情,並且實現必須記錄它做出的選擇 例如,是否可以通過多個進程打開單個文件是實現定義的。

未指明的行為是標准列出幾個備選方案的地方,因此每個備選方案都符合標准,但不再進一步。 實現必須選擇其中一個替代方案來選擇特定情況,但不必每次都做同樣的事情,並且不必在文檔中提交它將做出哪些選擇。 例如, struct中的填充位未指定。

未定義的行為是最極端的情況。 所有的賭注都關閉了。 如果編譯器或它生成的程序遇到未定義的行為 ,它可以做任何事情:它可以擾亂內存,破壞堆棧, HCF,或者在標准的極端情況下,導致惡魔飛出你的鼻子。 但大多數情況下它只會崩潰。 所有這些行為都符合標准。 例如,如果變量同時聲明為static int i; int i; 在相同的范圍內,或者如果你寫#include <'my file'.h> ,效果是不確定的。

“價值”有類似的定義。

未指定的值是有效值,但標准沒有說明它是什么。 因此,標准可能會說給定函數返回未指定的值。 您可以存儲該值並在需要時查看它,而不會導致錯誤,但這並不意味着什么,並且該函數可能會在下次返回不同的值,具體取決於月亮的相位。

實現定義的值類似於實現定義的行為。 就像未指定的那樣 ,它是一個有效的值,但是實現的文檔必須在將要返回的內容上提交,並且每次都執行相同的操作。

一個不確定的值未指定的更加未指定 它可以是未指定的值或陷阱表示 陷阱表示是標准 - 代表一些神奇的價值,如果你試圖將它分配給任何東西,會導致不確定的行為。 這不一定是實際價值; 可能最好的思考方式是“如果C有異常,陷阱表示將是一個例外”。 例如,如果您聲明int i; 在一個塊中,沒有初始化,變量i的初始值是不確定的 ,這意味着如果在初始化之前嘗試將其分配給其他東西,則行為是未定義的,並且編譯器有權嘗試所述的惡魔鼻子戲法。 當然,在大多數情況下,編譯器會做一些不那么戲劇性/有趣的事情,比如將其初始化為0或其他一些隨機有效值,但無論它做什么,你都無權反對。

所有這些不精確的關鍵是為編譯器編寫者提供最大的自由度。 這對於編譯器編寫者來說很好(這也是讓C編譯器在如此大范圍的平台上運行相當容易的原因之一),但它確實讓窮人用戶感到有趣而不是有趣。

編輯1 :澄清不確定的值。

編輯2 :包含C ++標准的鏈接,並注意委員會草案基本上等同於最終標准,但是免費。

我認為標准提到了未定義的行為和不確定的價值 所以一個是關於行為而另一個關於價值觀。

這兩者在某種程度上是正交的,例如,在存在不確定值的情況下仍然可以很好地定義行為。

編輯1: C11和C ++ 11的最后草稿可在線獲取: C11草案N1570C ++ 11草案n3242如果您沒有最終標准的副本並且它們看起來很棒。 (已經完成了對文本外觀和一些措辭/語法編輯的其他調整。)

編輯2:修正所有出現的“行為”為“行為”以匹配標准。

搜索C ++ 11和C11標准時, 不確定規則未定義規則沒有匹配項。 存在諸如不確定值不確定序列不確定未初始化等術語。

如果在Norman Gray的答案中談論陷阱和異常似乎很奇怪,請知道這些術語確實反映了C11標准 第3節中的相關定義。

C ++依賴於C的定義。 關於行為類型的許多有用定義可以在C11的第3節(C11中)中找到。 例如, 不確定值在3.19.2中定義。 請注意,C11的第2節(規范性引用文件)提供了其他術語解釋的其他來源,第4節定義了由於不遵守標准而發生未定義行為等情況。

C11的3.4節定義了行為 ,3.4.1定義了實現定義的行為 ,3.4.2定義了特定於語言環境的行為 ,3.4.3定義了未定義的行為 ,3.4.4定義了未指定的行為 對於 (第3.19節),有實現定義的值不確定的值未指定的值

簡而言之,術語“ 不確定”是指未指定/未知狀態 ,其本身不會導致未定義的行為 例如,這個C ++代碼涉及一個不確定的值:{int x = x; }。 (這實際上是C ++ 11標准中的一個例子。)這里x被定義為第一個整數,但此時它沒有明確定義的值 - 然后它被初始化為任何(不確定/未知)它有價值!

眾所周知的術語未定義行為在C11中的3.4.3中定義,並且指的是a的任何情況

不可移植或錯誤的程序構造或錯誤數據,本國際標准不對此要求

換句話說, 未定義的行為是一些錯誤(在邏輯或狀態中),接下來發生的任何事情都是未知的! 因此,可以制定一個未定義的[行為]規則 ,指出:在編寫C / C ++代碼時避免未定義的行為! :-)

不確定的[行為]規則將指出:避免編寫不確定的代碼, 除非需要它並且它不會影響程序的正確性或可移植性。 因此,與未定義的行為不同,不確定的行為並不一定意味着代碼/數據是錯誤的,但是, 其后續使用可能會或可能不會是錯誤的 -因此需要注意確保維持程序的正確性。

其他術語如不確定序列在正文中(例如,C11 5.1.2.3第3段; C ++ 11,第1.9節第13段;即[intro.executation])。 (正如您可能猜到的,它指的是未指定的操作步驟順序。)

IMO如果對所有這些細微差別感興趣,那么獲得C ++ 11和C11標准是必須的。 這將允許人們通過定義等探索所需的詳細程度。如果您沒有這樣的鏈接,將幫助您使用上次發布的C11和C ++ 11標准草案進行探索。

暫無
暫無

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

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