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; 否
-> 以指针方式访问成员 ptr->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 << 位元左移 int flags = 33 << 1;
>> 位元右移 int flags = 33 >> 1;
8 <=> 三路比较(C++20) auto flags = 33 <=> 1;
9 < 小于关系 if (i < 42) …
<= 小于等于关系 if (i <= 42) ...
> 大于关系 if (i > 42) …
>= 大于等于关系 if (i >= 42) ...
10 == 等于关系 if (i == 42) ...
!=
not_eq
不等于关系
!=的备用拼写
if (i != 42) …
11 &
bitand
位元 AND
&的备用拼写
flag1 = flag2 & 42;
12 ^
xor
位元 XOR(独占or)
^的备用拼写
flag1 = flag2 ^ 42;
13 |
bitor
位元 OR(包含or)
|的备用拼写
flag1 = flag2 | 42;
14 &&
and
逻辑 AND
&&的备用拼写
if (conditionA && 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;
<<= 以位元左移赋值 flags <<= 2;
>>= 以位元右移赋值 flags >>= 2;
&=
and_eq
以位元AND赋值
&=的备用拼写
flags &= 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 < b是是
小於或等於a <= b是是
大於a > b是是
大於或等於a >= b是是
不等於a != b是是
等於a == b是是
邏輯取反!a是是
邏輯 ANDa && b是是
邏輯 ORa || b是是
三路比较a <=> b是否

位元運算子

運算子名稱 語法 可重載 C语言裡有
位元左移a << b是是
以位元左移賦值a <<= b是是
位元右移a >> b是是
以位元右移賦值a >>= b是是
位元一的補數~a是是
位元 ANDa & b是是
以位元 AND 賦值a &= b是是
位元 ORa | b是是
以位元 OR 賦值a |= b是是
位元 XORa ^ b是是
以位元 XOR 賦值a ^= b是是

其它運算子

運算子名稱 語法 可重載 C语言裡有
基本賦值a = b是是
函式呼叫a()是是
陣列下標a[b]是是
間接(向下參考)*a是是
的位址(參考)&a是是
成員指標a->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语言裡有 提供者
標籤值&& 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))

這是一個有效的表達式。

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

   a & b == 7

意謂

   a & (b == 7)

而

   a + b == 7

意謂

   (a + b) == 7

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

一元正号运算符可用于操作数表达式的类型提升。例如下例:

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- 溢位,包裹,截裁 ?: 無
= |= 截裁 < 無 <=>
+= << 溢位,包裹,截裁 > 無

參閱

參考資料

  1. . [2007-03-01]. (原始内容存档于2015-02-03).

外部連結

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.