運算符是構建表達式的基石,理解優先級、結合性、操作數類型轉換規則,是編寫無 Bug 表達式的前提。本文系統梳理 C++ 所有運算符分類、優先級表、關鍵運算符語義、隱式類型轉換規則、常見表達式陷阱,提供查閱表與實戰代碼驗證。
| 分類 | 代表運算符 | 目數 |
|---|---|---|
| 後綴 | () [] -> . ++ -- | 1 |
| 一元/前綴 | ++ -- + - ! ~ * & sizeof new delete | 1 |
| 類型轉換 | (type) | 1 |
| 成員指針 | .* ->* | 2 |
| 算術 | * / % + - | 2 |
| 移位 | << >> | 2 |
| 關系 | < <= > >= | 2 |
| 相等性 | == != | 2 |
| 位與 | & | 2 |
| 位異或 | ^ | 2 |
| 位或 | | | 2 |
| 邏輯與 | && | 2 |
| 邏輯或 | || | 2 |
| 條件 | ? : | 3 |
| 賦值 | = += -= *= /= %= &= ^= |= <<= >>= | 2 |
| 逗號 | , | 2 |
1. :: 域解析 左→右 2. () [] -> . ++-- 後綴/成員訪問 左→右 3. ++ -- + - ! ~ * & sizeof new delete 一元/前綴 右→左 4. .* ->* 成員指針 左→右 5. * / % 乘除模 左→右 6. + - 加減 左→右 7. << >> 移位 左→右 8. < <= > >= 關系 左→右 9. == != 相等性 左→右 10. & 位與 左→右 11. ^ 位異或 左→右 12. | 位或 左→右 13. && 邏輯與 左→右 (短路) 14. || 邏輯或 左→右 (短路) 15. ? : 條件運算符 右→左 16. = += -= ... 賦值運算符 右→左 17. , 逗號運算符 左→右
口訣:單目 > 算術 > 移位 > 關系 > 相等 > 位運算 > 邏輯與 > 邏輯或 > 條件 > 賦值 > 逗號。
< <= > >=)== !=。bool (true/false)。a < b < c 解析為 (a < b) < c,**非數學意義**,C++20 引入 a < b < c 合法但極少用。== !=)nullptr 只能與指針比較。fabs(a-b) < eps。? :) —— 唯一三目運算符
條件 ? 表達式1 : 表達式2
// 相當於
if (條件) 表達式1; else 表達式2;
a ? b : c ? d : e 等價 a ? b : (c ? d : e)。! && ||) —— 短路求值| 運算符 | 優先級 | 結合性 | 短路規則 |
|---|---|---|---|
! | 2 (最高) | 右→左 | 無 |
&& | 13 | 左→右 | 左操作數為 false → 不計算右側 |
|| | 14 | 左→右 | 左操作數為 true → 不計算右側 |
實戰利用短路:if (ptr && ptr->valid()) 避免空指針解引用;if (file.open() || createNewFile())。
& | ^ ~ << >>)~ 按位取反,& 清零/掩碼,| 置位,^ 翻轉/交換。x << n 等價 x * 2^n,右移有符號數為算術移位(符號位擴展),無符號為邏輯移位(補 0)。= += ...)a = b = c = 1 等價 a = (b = (c = 1))。a += b 等價 a = a + b 但 a 只求值一次(對複雜表達式如 arr[i++] += 1 有差異)。bool, char, signed char, unsigned char, short, unsigned short, enum → 提升為 int (若 int 不能表示所有值則為 unsigned int)。
long double → 另一轉 long double。double → 另一轉 double。float → 另一轉 float。unsigned long long → 轉 unsigned long longlong long → 轉 long longunsigned long → 轉 unsigned longlong → 轉 longunsigned int → 轉 unsigned intint。簡化版:浮點型按精度向高轉;整型先提升,再按「無符號優先、長度優先」轉換。
#include
using namespace std;
int main() {
// 1. 優先級陷阱
int a = 3, b = 2, c = 1;
cout << "a > b == c: " << (a > b == c) << endl; // (a>b) 是 1(true), 1 == c(1) → true(1)
// 2. 短路求值
int x = 0, y = 0;
if (x++ && ++y) {} // x++ 為 0(false),短路,y 不自增
cout << "x=" << x << " y=" << y << endl; // x=1, y=0
// 3. 條件運算符嵌套
int m = 10, n = 20, p = 30;
int r = m > n ? m : n > p ? n : p; // m>n 假 → n>p 假 → p(30)
cout << "r=" << r << endl;
// 4. 後置++ 返回右值
int i = 1;
// i++++ 錯誤:後置++返回右值,不能再++
// 前置++ 返回左值
++++i; // 合法:(++(++i)),i 變 3
cout << "i=" << i << endl;
// 5. 同一表達式多次後置++
int x1 = 1;
int y1 = (x1++) + (x1++); // 兩次用舊值 1+1=2,序列點後 x1=3
cout << "y1=" << y1 << " x1=" << x1 << endl; // y1=2, x1=3
// 6. sizeof vs strlen
char str[] = "hello";
cout << "sizeof=" << sizeof(str) << " strlen=" << strlen(str) << endl; // 6 vs 5
// 7. 整型提升
char c = 200; // 有符號 char 可能溢出,視實現定義
cout << "c+1=" << (c+1) << endl; // c 提升為 int 運算
return 0;
}
i = i++ + ++i)為未定義行為 (C++17 前) 或未指定行為。fabs(a-b) < 1e-9。enum class:強類型,避免隱式轉換為整數參與運算。