2012-07-15 48 views
9

好的,我在Ideone上亂搞,不小心提交了這段代碼,但是令我驚訝的是,它實際上編譯並運行輸出0的值,here爲什麼在Ideone上編譯?

#include <iostream> 

using namespace std; 

const int five() 
{ 
     const int i = 5; 
} 

int main() { 
     cout << five() << endl; 
     return 0; 
} 

然後我想這在Visual Studio中,並在Codepad但都無法編譯,因爲five()沒有返回值,正如人們所期望的那樣。我的問題當然是,爲什麼這個編譯好在Ideone上,即使代碼,我的理解是錯誤的,不應該編譯。

回答

14

平原和簡單地(從C++ 11 6.6.3「return語句」):

流動關閉的功能的端部是相當於沒有值的返回;這會導致值返回函數中的未定義行爲。

所以編譯器幾乎可以做任何想做的事情。顯然,診斷是我希望從編譯器中得到的東西,但有時候很難診斷(比如返回是在條件邏輯內部,並且永遠不會達到函數的'結束')。

注意,我與GCC 4.6.1(使用Wall選項)以下警告:

test.cpp:8:1: warning: no return statement in function returning non-void [-Wreturn-type] 

我不知道ideone傳遞給GCC哪些選項(我想象-Wall會做同樣的與ideone使用的4.3.4版本)。

一些相關的信息:

在C語言中它是被聲明爲返回值的函數確定,實際上沒有這樣做在某些情況下,在C中,如果函數的返回值實際上是,則只會導致未定義的行爲。 Pre-standard C並不總是支持void類型,所以沒有返回任何東西的函數經常被聲明爲顯式或隱式地返回int。從C99 6.9.1/12「函數定義」:如果達到了終止函數的},並且函數調用的值由調用方使用,則行爲是未定義的。

此外,正如一些評論中提到的那樣,流出main()的末尾會被C++和C99以及更高版本專門處理。

+0

您能否參考報價的來源? – 2012-07-15 20:23:01

+0

@DesmondHume:標準。 – Xeo 2012-07-15 20:23:26

+1

唯一一次定義明確的是'main' – 2012-07-15 20:24:26

3

不從一個非void函數返回一個值是一個錯誤,但不是所有的編譯器都將它視爲一個錯誤 - 例如,GCC在遇到這個時只會發出警告。其他編譯器可能是偏執狂(他們是對的),不要讓你編譯這樣的代碼。當然,編譯器行爲可以使用不同的開關和選項進行修改。

0的返回值只是一個隨機值 - 它可能同樣是255,-1或任何其他垃圾,因爲這樣做是未定義的行爲(除了main,C99指定一個隱式的0返回值應該被假定)。

3

它似乎ideone不顯示警告,它只顯示編譯器輸出,如果有錯誤。在ideone使用的GCC版本(gcc 4.3)上,這不是一個錯誤,它只是一個警告。

2

該代碼具有未定義的行爲。即使你所做的是錯誤的,編譯器也不需要診斷它。另一點是ideone使用現在相當老版本的gcc。一個合理的當前版本的gcc(例如4.7)至少會給你一個警告,告訴你的函數聲明返回一個值,但不是 - 但不是默認值。你必須用類似-Wall的東西來打開它才能得到警告(但作爲一般規則,我會總是使用至少-Wall與gcc)。