2010-11-04 54 views
2

我的鉗宏問題,當我的值超過10,我的高超過17時,它停止工作。任何想法?我的鉗宏問題

#define CLAMP(value, low, high) (((value)<(low))?(low):(((value)>(high))?(high):(value))) 
+0

調試宏時要做的第一件事是展開它,看看爲什麼你會得到不正確的結果。 – 2010-11-04 19:49:58

回答

15

我會建議使用更安全的方式比宏:

template <typename T> T CLAMP(const T& value, const T& low, const T& high) 
{ 
    return value < low ? low : (value > high ? high : value); 
} 
+1

+1,但我建議'template ' – Beta 2010-11-04 19:53:01

+0

+1 for function over a macro – luke 2010-11-04 19:55:43

+0

@Beta:這樣它會捕獲潛在危險的類型轉換。但是你的方法也會起作用。 – 2010-11-04 19:55:43

4

您的宏是好的。如果您通過的high小於low,您會看到奇怪的結果,但這不太可能是原因。

最可能的結果是,您傳遞的是具有副作用的表達式,例如使用++運算符或調用函數。如果您的表情有副作用,那麼由於宏觀替代的作用方式,副作用可能會發生多次。例如:

CLAMP(x++, low, high) // expands to: 
(x++ < low) ? low : ((x++ > high) ? high : x++); 

x++被多次評估,這絕對不是你想要的(這是不確定的行爲,由於缺乏一個序列點)。

我建議重寫宏作爲一個模板:

template <typename T> T CLAMP(T value, T low, T high) 
{ 
    return (value < low) ? low : ((value > high) ? high : value); 
} 
+0

爲什麼即使保持三元運算符?爲什麼不用兩個'if'語句和三個'return'來重寫呢? – 2010-11-04 19:57:43

0

你也可以把它的inline功能,因此它會像宏但更安全。

1

使用已經建議的模板函數是一個更好的解決方案。無論如何,如果你有這樣的問題(無論是用宏還是函數),你都應該簡化表達式;看看這個僞代碼:

max(a,b): a>b ? a : b 
min(a,b): a<b ? a : b 
clamp(x,lo,hi): min(hi, max(lo,x))