2009-08-06 37 views
29

瀏覽Linux內核源我發現some piece of code其中由括號包圍的語句塊被視爲表達一拉口齒不清(或ML),即,該值是最後語句的值的表達式。ANSI C中parens表達式包圍的複合語句(塊)?

例如:

int a = ({ 
    int i; 
    int t = 1; 
    for (i = 2; i<5; i++) { 
     t*=i; 
    } 
    t; 
}); 

我一直在尋找的ANSI C grammar試圖找出如何這段代碼將適合解析樹,但我都沒有成功。

那麼,有沒有人知道這種行爲是由標準強制還是僅僅是GCC的特性?

更新:我試過用標誌-pedantic和編譯器現在給我一個警告:

warning: ISO C forbids braced-groups within expressions 

回答

28

這就是所謂的「表達中摻進組」。

它不被ANSI/ISO C和C++所允許,但gcc支持它。

+7

通過在左括號之前放置__extension__,可以抑制GCC中的警告。 – Flimm 2014-09-25 14:42:10

28

這是一個gcc擴展名爲statement expressions,你可以找到完整的C擴展名列表here。這實際上是many gcc extensions used in the Linux kernel之一,它看起來像clang supports this too,雖然它沒有明確命名在文檔中。

正如你所觀察到的最後一個表達式作爲表達式的值,該文件說(重點煤礦):

複合語句的最後一點要表達一個分號;該子表達式的值用作整個構造的值。 (如果你使用一些其他類型的語句最後的括號內,該結構的類型爲void,因此沒有有效的值。)

的一個主要好處是使安全宏將避免多有副作用的論證評估。這個例子採用這種不安全的宏:

#define max(a,b) ((a) > (b) ? (a) : (b)) 

其評估或者ab兩次,可以改寫using語句表述如下,以消除此問題:

#define maxint(a,b) \ 
    ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) 

注意,需要明確使用int其可以使用另一個gcc分機Typeof固定:

#define max(a,b) \ 
    ({ typeof (a) _a = (a), _b = (b); _a > _b ? _a : _b; }) 

請注意,clang also supports typeof

+0

如果沒有語句表達式,就可以編寫一個像這樣安全的宏嗎? – Flimm 2014-09-25 14:38:17

+0

@Flimm我不這麼認爲,但我不認爲自己是一位宏觀專家。我儘可能避免它們,儘管有些情況下很難避免,比如滾動自己的斷言。 – 2014-09-26 01:24:22

+0

@Flimm這取決於你想要你的宏做什麼,在某些情況下,寫一個安全的宏當然是可能的。對於完整的'max'功能,無論你在標準C中做什麼,都會失敗 - 問題是你需要知道參數的類型,或者你必須評估其中一個兩次(其中的以後是上述宏觀方法的問題)。 – skyking 2017-05-03 13:17:27