2011-03-16 40 views
8
#define max(a,b) \ 
    ({ typeof (a) _a = (a); \ 
     typeof (b) _b = (b); \ 
    _a > _b ? _a : _b; }) 

爲什麼不簡單(a>b ? a : b)爲什麼在C中定義這樣的'max'宏?

+3

請注意,typeof是您在GCC擴展中可能遇到的非標準關鍵字。在嚴格的C/C++編譯器中,typeof()將不會編譯。 – Lundin 2011-03-16 10:40:48

+2

因爲GNU的人寧願有醜陋的,不可讀的代碼充滿GNU特定的黑客,而不是簡單地說明您不能將具有副作用的表達式傳遞給宏... – 2011-03-16 12:55:47

回答

19

因爲otherwhise max(f(1), f(2))會叫的兩個功能一個兩次:

f(1) > f(2) ? f(1) : f(2) 

通過,而不是「緩存」在_a兩個值和_b你有

({ 
    sometype _a = (a); 
    sometype _b = (b); 

    _a > _b ? _a : _b; 
}) 

(和其他有清楚指出,有自動增量/自動減量相同的問題)

我不認爲這是由Visual S支持以這種方式。這是一個複合陳述。讀到這裏does msvc have analog of gcc's ({ })

我補充一點,在這裏http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62給出的GCC手冊的複合語句定義顯示出非常相似的最大的問題之一:-)

8

它讓周圍的主要問題代碼之類的東西

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

當你把它叫做:

int x = max (a++, b--); 

因爲它是簡單的文本替換,導致:

int x = ((a++) > (b--) ? a++ : b--); 

這是你想要什麼。

使用:

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

它使用的臨時變量,有效地爲您提供:

int x = ({ int _a = a++; int _b = b--; _a > _b ? _a : _b; }) 

它運行的副作用只有一次。

不過,說實話,你應該溝宏觀乾脆使用inline功能,甚至一個非內聯函數,因爲,大多數時候,編譯器可以做優化的一份體面的工作,即使沒有那個建議。

1

如果使用表達式調用宏,這可能會導致意外的行爲。假設這樣的:

int c = max(i++, j++);

在這種情況下,最大是與簡單的版本提升兩倍。

+0

更可能的調用是'max(* p ++,* q ++)'。 – 2011-03-16 11:47:56

3

的另一種方法,以確定最大值(至少對於正數)

#define MAX(a,b) sizeof(union x { char ca[a]; char cb[b];}) 

作爲a和b是隻訪問一次的,MAX(一個++,B ++)給出正確的結果。

+0

我可以確定編譯器沒有實際實例化聯合? – pezcode 2011-10-20 19:21:44