問題

C和C中的未定義行為是什麼?未指定的行為和實現定義的行為是什麼?它們之間有什麼區別?

  最佳答案

未定義的行為是來自其他語言的程式設計師可能會感到驚訝的C和C語言的一個方面(其他語言嘗試更好地隱藏它).基本上,可以編寫不以可預測方式表現的C程式,即使許多C編譯器不會報告程式中的任何錯誤!

讓我們看一個典型的例子:

 #include <iostream>

int main()
{
    char* p = "hello!
";   // yes I know, deprecated conversion
    p[0] = 'y';
    p[5] = 'w';
    std::cout << p;
}
 

變數p指向字串文字"hello! ",下面的兩個任務嘗試修改該字串文字.這個程式做了什麼?根據C標準第2.14.5段,它呼叫未定義的行為:

嘗試修改字串文字的效果未定義。

我可以聽到人們尖叫“但等待,我可以編譯這個沒有問題,並得到輸出yellow”或“你的意思是什麼未定義,字串文字儲存在只讀記憶體中,所以第一個分配嘗試會導致核心轉儲.”這正是未定義行為的問題.基本上,一旦你呼叫未定義的行為(甚至鼻惡魔),標準允許發生任何事情.如果根據語言的精神模型有“正確”的行為,那麼模型就是錯誤的;C標準只有投票,週期.

其他未定義行為的例子包括訪問超出其界限的陣列,解除引用空指標,在其生命週期結束後訪問物件或寫據稱聰明的表示式,如i++ + ++i.

C標準的第1.9節還提到未定義的行為的兩個不太危險的兄弟,未指定的行為和實現定義的行為:

本國際標準中的語義描述定義了一個引數化的非確定性抽象機器。

本國際標準將抽象機的某些方面和操作描述為 implementation-defined(例如,sizeof(int))。

本國際標準將抽象機的某些其他方面和操作描述為未指明的(例如,對函式引數的評估順序).在可能的情況下,本國際標準定義了一組允許行為.這些定義了抽象機的非確定性方面.

本國際標準將某些其他操作描述為未定義(例如,取消引用空指標的效果)。

具體而言,第1.3.24節規定:

允許的未定義行為包括:完全無視情況,結果難以預測;在翻譯或程式執行過程中以環境特徵的記錄方式行事(發出或不發出診斷資訊);終止翻譯或執行(發出診斷資訊)。

你可以做些什麼來避免進入未定義的行為?基本上,你必須閱讀好的C books 的作者知道他們在說什麼.螺桿網際網路教程.螺桿牛仔。