C和C++運算子

所有的C語言運算符都被C++語言支持。C語言不支持運算符重載。

在不重載時，運算符`&&`、`

`、`,`（逗號運算符），在第一個操作數求值之後有一個順序點。

大部分C與C++運算符也可用於其它程序設計語言如C#、Java、Perl、PHP等，具有相同的優先級、結合性與語義。

## 運算子優先級

以下是C++程式語言中的所有運算子的優先級和結合性列表。

優先級｜運算子｜敘述｜示例｜重載性｜結合性

`1`｜`::`｜作用域解析(C++專有)｜`Class::age = 2;`｜否｜由左至右

`2`｜`++`｜後綴遞增｜`i++`

`--`｜後綴遞減｜`i--`

`()`｜函數調用或函數調用形式的類型轉換｜`int x = f();`

`[]`｜陣列訪問｜`array[4] = 2;`

`.`｜以對象方式訪問成員｜`obj.age = 34;`｜否

`-&gt;`｜以指針方式訪問成員｜`ptr-&gt;age = 34;`

`dynamic_cast`｜運行時檢查類型轉換(C++專有)｜`Y& y = dynamic_cast<Y&>(x);`｜否

`static_cast`｜未經檢查的類型轉換(C++專有)｜`Y& y = static_cast<Y&>(x);`｜否

`reinterpret_cast`｜重定義類型轉換(C++專有)｜`int const* p = reinterpret_cast<int const*>(0x1234);`｜否

`const_cast`｜更改非常量屬性(C++專有)｜`int* q = const_cast<int*>(p);`｜否

`typeid`｜獲取類型資訊(C++專有)｜`std::type_info const& t = typeid(x);`｜否

`3`｜`++`｜前綴遞增｜`++i`｜由右至左

`--`｜前綴遞減｜`--i`

`+`｜一元正號｜`int i = +1;`

`-`｜一元負號｜`int i = -1;`

`!``not`｜邏輯非`!`的備用拼寫｜`if (!done) …`

`~``compl`｜按位取反`~`的備用拼寫｜`flag1 = ~flag2;`

`(''type'')`｜強制類型轉換｜`int i = (int)floatNum;`

`*`｜取指針指向的值｜`int data = *intPtr;`

`&`｜取變量的地址｜`int *intPtr = &data;`

`sizeof`｜某某的大小｜`size_t s = sizeof(int);`｜否

`new`｜動態記憶體分配(C++專有)｜`long* pVar = new long;`

`new[]`｜動態數組記憶體分配(C++專有)｜`long* array = new long[20];`

`delete`｜動態記憶體釋放(C++專有)｜`delete pVar;`

`delete[]`｜動態數組記憶體釋放(C++專有)｜`delete [] array;`

`4`｜`.*`｜成員對象選擇(C++專有)｜`obj.*var = 24;`｜否｜由左至右

`->*`｜成員指針選擇(C++專有)｜`ptr->*var = 24;`

`5`｜`*`｜乘法｜`int i = 2 * 4;`

`/`｜除法｜`float f = 10.0 / 3.0;`

`%`｜模數（取餘數）｜`int rem = 4 % 3;`

`6`｜`+`｜加法｜`int i = 2 + 3;`

`-`｜減法｜`int i = 5 - 1;`

`7`｜`&lt;&lt;`｜位元左移｜`int flags = 33 &lt;&lt; 1;`

`&gt;&gt;`｜位元右移｜`int flags = 33 &gt;&gt; 1;`

`8`｜`&lt;=&gt;`｜三路比較（C++20）｜`auto flags = 33 &lt;=&gt; 1;`

`9`｜`&lt;`｜小於關係｜`if (i &lt; 42) …`

`&lt;=`｜小於等於關係｜`if (i &lt;= 42) ...`

`&gt;`｜大於關係｜`if (i &gt; 42) …`

`&gt;=`｜大於等於關係｜`if (i &gt;= 42) ...`

`10`｜`==`｜等於關係｜`if (i == 42) ...`

`!=``not_eq`｜不等於關係`!=`的備用拼寫｜`if (i != 42) …`

`11`｜`&amp;``bitand`｜位元 AND`&amp;`的備用拼寫｜`flag1 = flag2 &amp; 42;`

`12`｜`^``xor`｜位元 XOR(獨占or)`^`的備用拼寫｜`flag1 = flag2 ^ 42;`

`13`｜`|``bitor`｜位元 OR(包含or)`|`的備用拼寫｜flag1 = flag2 `|` 42;

`14`｜`&amp;&amp;``and`｜邏輯 AND`&amp;&amp;`的備用拼寫｜`if (conditionA &amp;&amp; conditionB) …`

`15`｜`||``or`｜邏輯 OR`||`的備用拼寫｜if (conditionA `||` conditionB) ...

`16`｜`''c''?''t'':''f''`｜三元條件運算｜`int i = a > b ? a : b;`｜否｜由右至左

`17`｜`=`｜直接賦值｜`int a = b;`

`+=`｜以和賦值｜`a += 3;`

`-=`｜以差賦值｜`b -= 4;`

`*=`｜以積賦值｜`a *= 5;`

`/=`｜以商賦值｜`a /= 2;`

`%=`｜以取餘數賦值｜`a %= 3;`

`&lt;&lt;=`｜以位元左移賦值｜`flags &lt;&lt;= 2;`

`&gt;&gt;=`｜以位元右移賦值｜`flags &gt;&gt;= 2;`

`&amp;=``and_eq`｜以位元AND賦值`&amp;=`的備用拼寫｜`flags &amp;= new_flags;`

`^=``xor_eq`｜以位元XOR賦值`^=`的備用拼寫｜`flags ^= new_flags;`

`|`=`or_eq`｜以位元OR賦值`|`=的備用拼寫｜flags `|`= new_flags;

`18`｜`throw`｜拋出異常｜`throw EClass("Message");`｜否

`19`｜`,`｜逗號運算子｜`for (i = 0, j = 0; i < 10; i++, j++) …`｜由左至右

## 列表

在本表中，`a`、`b`和`c`代表有效值（來自變數或返回值的逐字常數或數值）、物件名稱，或適當的左值。

### 算術運算子

運算子名稱｜語法｜可重載｜C語言裡有

一元正號｜`'''+'''a`｜是｜是

加法（總和）｜`a '''+''' b`｜是｜是

前綴遞增｜`'''++'''a`｜是｜是

後綴遞增｜`a'''++'''`｜是｜是

以加法賦值｜`a '''+=''' b`｜是｜是

一元負號（取反）｜`'''-'''a`｜是｜是

減法（差）｜`a '''-''' b`｜是｜是

前綴遞減｜`'''--'''a`｜是｜是

後綴遞減｜`a'''--'''`｜是｜是

以減法賦值｜`a '''-=''' b`｜是｜是

乘法（乘積）｜`a '''*''' b`｜是｜是

以乘法賦值｜`a '''*=''' b`｜是｜是

除法（分之）｜`a '''/''' b`｜是｜是

以除法賦值｜`a '''/=''' b`｜是｜是

模數（餘數）｜`a '''%''' b`｜是｜是

以模數賦值｜`a '''%=''' b`｜是｜是

### 比較運算子

運算子名稱｜語法｜可重載｜C語言裡有

小於｜`a '''&lt;''' b`｜是｜是

小於或等於｜`a '''&lt;=''' b`｜是｜是

大於｜`a '''&gt;''' b`｜是｜是

大於或等於｜`a '''&gt;=''' b`｜是｜是

不等於｜`a '''!=''' b`｜是｜是

等於｜`a '''==''' b`｜是｜是

邏輯取反｜`'''!'''a`｜是｜是

邏輯 AND｜`a '''&amp;&amp;''' b`｜是｜是

邏輯 OR｜a `||` b｜是｜是

三路比較｜`a '''&lt;=&gt;''' b`｜是｜否

### 位元運算子

運算子名稱｜語法｜可重載｜C語言裡有

位元左移｜`a '''&lt;&lt;''' b`｜是｜是

以位元左移賦值｜`a '''&lt;&lt;=''' b`｜是｜是

位元右移｜`a '''&gt;&gt;''' b`｜是｜是

以位元右移賦值｜`a '''&gt;&gt;=''' b`｜是｜是

位元一的補數｜`'''~'''a`｜是｜是

位元 AND｜`a '''&amp;''' b`｜是｜是

以位元 AND 賦值｜`a '''&amp;=''' b`｜是｜是

位元 OR｜a `|` b｜是｜是

以位元 OR 賦值｜a `|`= b｜是｜是

位元 XOR｜`a '''^''' b`｜是｜是

以位元 XOR 賦值｜`a '''^=''' b`｜是｜是

### 其它運算子

運算子名稱｜語法｜可重載｜C語言裡有

基本賦值｜`a '''=''' b`｜是｜是

函式呼叫｜`a'''()'''`｜是｜是

陣列下標｜`a'''['''b''']'''`｜是｜是

間接（向下參考）｜`'''*'''a`｜是｜是

位址（參考）｜`'''&amp;'''a`｜是｜是

成員指標｜`a'''-&gt;'''b`｜是｜是

成員｜`a'''.'''b`｜否｜是

間接成員指標｜`a'''->*'''b`｜是｜否

間接成員｜`a'''.*'''b`｜否｜否

轉換｜`(''type'') a`｜是｜是

逗號｜`a ''',''' b`｜是｜是

三元條件｜`a '''?''' b ''':''' c`｜否｜是

作用域解析｜`a'''::'''b`｜否｜否

大小｜`'''sizeof''' a`｜否｜是

類型識別｜`'''typeid''' ''type''`｜否｜否

分配儲存區｜`'''new''' ''type''`｜是｜否

解除分配儲存區｜`'''delete''' a`｜是｜否

### 語言擴展

運算子名稱｜語法｜可重載｜C語言裡有｜提供者

標籤值｜`'''&amp;&amp;''' label`｜否｜是｜GCC

取得型態｜`'''typeof''' a``'''typeof'''(''expr'')`｜否｜是｜GCC

最小／最大值｜`a '''<?''' b``a '''>?''' b`｜否｜否｜GCC < 4.3

## 註解

在C和C++中對運算子的約束，是語言的語法規範因素所指定的（在對應的標準中），而不是優先級列表。這造成了一些微妙的衝突。例如，在C中，條件表達式的語法是：

```
   邏輯-OR-表達式 ? 表達式 : 條件-表達式
```

在C++中則是：

```
   邏輯-or-表達式 ? 表達式 : 賦值-表達式
```

因此，這個表達式：

```
   e = a ? b : c = d
```

兩個語言的語法分析結果並不相同。在C中，這個表達式被解析為：

```
   e = ((a ? b : c) = d)
```

這是一個錯誤的語義，因為條件-表達式的結果並不是一個左值。在C++中，則解析為：

```
   e = (a ? b : (c = d))
```

這是一個有效的表達式。

位元邏輯運算子的優先級一直受到批評。在觀念裡，&和|是類似於+和*的數值運算子。但是，表達式

```
   a & b == 7
```

意謂

```
   a & (b == 7)
```

而

```
   a + b == 7
```

意謂

```
   (a + b) == 7
```

這就需要經常使用圓括號，以免有意料之外的結果。

一元正號運算符可用於操作數表達式的類型提升。例如下例：

```cpp
template <class T> void f(T const& a, T const& b){};

int main() {
	int a[2];
	int b[3];
	f(a, b); // won't work! different values for "T"!
	f(+a, +b); // works! T is "int*" both
}
```

## 安全問題

下表指出了各個運算符可能導致的安全問題：

符號｜安全性｜符號｜安全性｜符號｜安全性｜符號｜安全性

+｜溢位,包裹,循環｜-=｜溢位,包裹,循環,截裁｜>>｜無｜>=｜無

溢位,包裹,循環｜、=｜溢位,包裹,循環,截裁｜&｜無｜`==`｜無

-｜溢位,包裹,循環｜/=｜溢位,截裁｜~｜無｜=｜無

%｜溢位｜<<=｜溢位,包裹,循環,截裁｜無｜&&｜無

++｜>>=｜截裁｜un+｜無｜`||`｜無

--｜&=｜截裁｜un-｜溢位,包裹,截裁｜?:｜無

=｜`|=`｜截裁

+=｜無

## 參閱

- C
- C++

## 外部連結

- Experimental results showing that developers have poor knowledge of binary operator precedence.
- Basic types & Operators