2011-09-28 71 views
9

在GCC 4.6中嘗試了這一點,它編譯和鏈接,但在運行時在MacOS上發出「總線錯誤」消息。 VS2010甚至沒有編譯它。這是正確的C++ 0x代碼嗎?

但問題是,如果這實際上工作在標準的C++ 0x?

#include <cstdio> 
int (*main)()=[]()->int{printf("HEY!\n");return 0;}; 

是的,它試圖做的是將「main」定義爲lambda函數。

+13

我喜歡你嘗試使用C++ 11的最新,最好的高級功能,但仍堅持使用'cstdio'和'printf' :-) – paxdiablo

+4

@paxdiablo:printf rocks !!! C++在I/O流失敗:) – 2011-09-28 12:58:23

+1

根據Stroustroup ...如果C讓你在腳下射擊,C++可以把你所有的腿擊倒!這就是我所說的......受虐狂! :-)) –

回答

14

這不是一個有效的C++程序,因爲符號main沒有被定義爲一個函數,而是一個指向函數的指針。這就是爲什麼你得到分段錯誤 - 運行時正試圖執行一個指針。

+0

+1 :(把我的馬虎評論刪除了原來的問題,這個回答更好的解釋了這裏發生了什麼。) –

+0

那麼我想這實際上是GCC中的一個錯誤,它接受這段代碼是正確的? – hasvn

+0

@hasvn,我不確定,但我認爲這是標準中不需要診斷的那些實例之一。所以海灣合作委員會可能是明確的。 – avakar

3

不,這是不正確的。

Main是一個特殊的函數,它對它有嚴格的要求(甚至比普通函數更嚴格),但是你也對函數的功能和指向函數的指針有些混淆。

邏輯問題是函數和變量之間存在一個指針函數的指針(你想要的主要是什麼)之間的區別。 一個函數在內存中有一個固定的地址,所以調用一個簡單調用地址的函數。一個函數指針指向到內存中的一個地址,所以調用你需要的函數首先讀取指針指向的內容,然後調用該地址。

指向函數的指針與函數具有不同的間接級別。

的語法是一樣的......也就是說,如果x是指向一個功能,你可以寫x(42),但仍生成的機器代碼是不同的,如果x是不是函數(在指針的值必須的情況下,被查詢並且呼叫地址在運行時被確定,具有地址被固定的功能 - 直到重定位 - 並且在鏈路時間被確定)。

0

對於編譯器和標準庫實現之間的可移植性,當#including <cstdio>時,printf()必須是std :: printf()。還有關於無效main()的其他內容。

+0

不,在標準中沒有規定'cXXX'是否包含注入全局名稱空間。使用'std ::'是_wise_,但是「must」可能是一種矯枉過正的行爲。 – paxdiablo

+0

好的,無論如何,這是一個半開玩笑。我將編輯答案,注意它是可移植性所必需的。 (我們這些編寫便攜代碼爲生的人開始思考這種方式......) –

0

現在,它甚至不應該編譯。 lambda表達式產生一個類型(一個函子)。 不存在從類型到函數指針的隱式轉換。

根據編譯器的不同,main函數可以有C++或C鏈接(它是實現定義的)。 Lambda表達式返回帶有函數調用操作符的C++類型,因此C++鏈接。

+0

實際上是從非捕獲的lambda到函數指針的隱式轉換。 – avakar

+0

引用:(5.1.2/6)。 –

+0

你們都是對的。雖然,它隱式轉換爲指向成員函數的指針,而不是自由函數。依稀記得那可能會讓我困惑。 – mloskot