C語言條件運算子(?:)

2020-07-16 10:04:20
條件運算子(conditional operator)有時候也稱為三元運算子(ternary operator,或者trinary operator),因為它是唯一需要 3 個運算元的運算子

條件 ? 表示式1 : 表示式2


條件運算操作會首先計算條件,然後根據條件的計算結果,再決定要計算兩個表示式中的哪一個。

在計算完條件之後,有一個序列點。如果結果不等於 0(換句話說,如果條件計算結果為 true),則只有第二個運算元(也就是表示式 1)會被計算,並且表示式 1 的值就是整個表示式的結果。

另一方面,如果結果為 0(如果條件計算結果為 false),那麼只有第三個運算元(也就是表示式 2)會被計算,並且表示式 2 的值就是整個表示式的結果。以這種方式,條件運算子代表了在程式流中的條件式跳轉,因此,有時候可以與 if-else 語句相互替代

下面是常見的例子,找出兩個數中的最大者:
inline int iMax(int a, int b) { return a >= b ? a : b; }

函數 iMax()可以用 if-else 語句改寫:
inline int iMax(int a, int b)
{ if ( a >= b ) return a; else return b; }

條件運算子具有相當低的優先順序,只有賦值和逗號運算子的優先順序比它低。因此,下面的語句不需要括號:
distance = x < y ? y - x : x - y;

條件運算子的第一個運算元是條件,必須是標量型別,也就是算術型別或指標型別。第二個和第三個運算元分別是表示式 1 和表示式 2,必須滿足下面條件之一:

(1) 兩個可選表示式都具有算術型別,在這種情況下,整個運算的最終結果型別,是後面兩個運算元進行尋常算術轉換的型別。

(2) 兩個可選運算元都有相同的結構或聯合型別,或者 void 型別。整個運算的最終結果型別也屬於與這兩個運算元一樣的型別。

(3) 兩個可選運算元都是指標,並且符合下面的一個條件:
     兩個指標屬於相同型別。整個運算的結果也屬於相同的型別。
     其中一個運算元是空指標常數。整個運算的結果屬於另一個運算元型別。
     其中一個運算元是物件指標,另一個是指向 void 指標。整個運算的結果屬於 void* 型別。

兩個指標可以指向具有不同限定符的型別。在這種情況下,整個運算的結果是一個指標,其所指的物件型別同時具備兩個可選運算元的型別限定符。例如,假設下面的指標以已定義:
const int *cintPtr;             // 宣告指標
volatile int *vintPtr;
void *voidPtr;

不管變數 flag 值是多少,下表中第一列所列舉的各表示式具有其第二列所描述的型別:
表示式 型別
flag ? cintPtr : vintPtr volatile  const  int*
flag ? cintPtr : NULL const  int*
flag ? cintPtr : voidPtr const  void*