2011-10-19 108 views
11

最近,我發現這個GCC宏:`({...})`如何返回值?

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

之前,我看到這個代碼,我沒有意識到,那個代碼{...}塊能以某種方式在C.
1)返回值可不可以給我一個提示這是如何工作的?

雖然,我通常能夠通過濫用逗號運算符來達到相同的結果:

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

,或者如果它僅是爲副作用,我會用do { ... } while(0)

2)什麼是這樣做的首選方式?

+1

可能成爲一個受保護的問題!許多C(和C++,我相信)程序員不知道'({...})'是GCC擴展,而不是C語言的一部分。恕我直言。 – Jack

回答

9

({ ... })構造是一個gcc擴展。

因此是typeof運營商。

一個MAX宏(請注意,常規採用全大寫的)是很容易寫:

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

它並評估其參數不止一次,所以你不應該調用它爲一個,例如,MAX(x++, y--)。使用全部大寫字母可以提醒用戶它是一個宏而不是一個函數,並且要注意帶有副作用的參數。

或者你可以爲每種類型寫一個函數(也許是一個內聯函數)。

+2

+1 Wow: - |,真的不知道'({...})'。他們應該完全用語言來表達。 – cnicutar

+2

感謝['({...})'](http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Statement-Exprs.html#Statement-Exprs)鏈接!只有標點符號,Google一直很難。 – Halst

10

這是一個GCC擴展。逗號操作符不工作:

// C89, doesn't work... 
#define max(a,b) \ 
    (typeof (a) _a = (a), \ 
    typeof (b) _b = (b), \ 
    (_a > _b ? _a : _b)) 

逗號操作符只能用表情作品,並typeof(a) _a = (a);是一個聲明,而不是表達。編寫沒有GCC擴展或C11的等效宏是不可能的,它具有_Generic。請注意,typeof也是GCC擴展名,因此您不會通過消除({...})獲得任何便攜性,除非您也消除typeof

這是一個C11版本,請注意它是如何詳細比較(它只處理兩種類型!)。 C11甚至沒有支持呢,好運氣試圖找到一個編譯器測試:

// C11 
static inline int maxi(int x, int y) { return x > y ? x : y; } 
static inline long maxl(long x, long y) { return x > y ? x : y; } 
#define max(x, y) _Generic((x), \ 
    long: maxl(x,y), \ 
    int:_Generic((y), \ 
     int: maxi(x,y), \ 
     long: maxl(x,y))) 

在便攜式C99,你可以寫一個宏或內聯函數的實現同樣的效果,除了僅會每個宏爲一種類型工作。

// C99 
static inline int maxi(int x, int y) { return x > y ? x : y; } 

在C89/C90,我想不出任何辦法寫的宏這樣一種方式,它不會評價xy兩次。

+7

請不要寫一個什麼都不說的答案。只需留下時間,寫出一個好的答案。如果它很好,它會得到很多讚揚。沒有必要嘗試和你自己的問題。 –

+0

對不起,我在一個陌生的終端,我正在試圖保存草稿,所以我不會丟失我寫的東西。並不是真的想「把自己的問題歸咎於自己」。 –

+1

好的,現在+1,優秀的答案 –