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