C和C++運算子

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

在不重載時,運算符&&||,逗號運算符),在第一個操作數求值之後有一個順序點

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

運算子優先級

以下是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++) … 由左至右

列表

在本表中,abc代表有效值(來自變數或返回值的逐字常數或數值)、物件名稱,或適當的左值。

算術運算子

運算子名稱 語法 可重載 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
邏輯 AND a && b
邏輯 OR a || b
三路比較 a <=> b

位元運算子

運算子名稱 語法 可重載 C語言裡有
位元左移 a << b
以位元左移賦值 a <<= b
位元右移 a >> b
以位元右移賦值 a >>= b
位元一的補數 ~a
位元 AND a & b
以位元 AND 賦值 a &= b
位元 OR a | b
以位元 OR 賦值 a |= b
位元 XOR a ^ 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. ^ The Development of the C Language. [2007-03-01]. (原始內容存檔於2015-02-03). 

外部連結