C++ 运算符
运算符(operator)是程序里"做计算"的符号——加号、等号、比较大小等等。C++ 提供了丰富的运算符,大部分你数学课就学过,少数是编程特有的(位运算、三元)。这一章我们一一过一遍。
一、算术运算符
最基础的加减乘除:
#include <iostream>
using namespace std;
int main() {
int a = 17, b = 5;
cout << a + b << endl; // 22 加法
cout << a - b << endl; // 12 减法
cout << a * b << endl; // 85 乘法
cout << a / b << endl; // 3 除法(整数除整数,直接舍去小数)
cout << a % b << endl; // 2 取余(只对整数)
// 整数除法的坑
cout << 7 / 2 << endl; // 3
cout << 7.0 / 2 << endl; // 3.5(只要有一个是浮点,就按浮点除)
// 自增自减
int i = 5;
cout << i++ << endl; // 5(先用再加)
cout << i << endl; // 6
cout << ++i << endl; // 7(先加再用)
return 0;
}注意几个坑:
- 整数除法:整数除整数结果还是整数(舍去小数),想得到小数要写
7.0 / 2。 - 取余 %:只能对整数用,浮点数取余用
fmod。 - i++ vs ++i:前者"先用再加",返回旧值;后者"先加再用",返回新值。循环里推荐
++i(理论更快,实际现代编译器都优化)。
二、关系运算符
用于比较两个值,返回 bool:
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 20;
cout << (a == b) << endl; // 0 (相等)
cout << (a != b) << endl; // 1 (不等)
cout << (a < b) << endl; // 1 (小于)
cout << (a > b) << endl; // 0 (大于)
cout << (a <= b) << endl; // 1 (小于等于)
cout << (a >= b) << endl; // 0 (大于等于)
// 关系运算返回 bool,在 C++ 里 cout 默认显示为 0/1
// 用 boolalpha 可以让它显示 true/false
cout << boolalpha << (a < b) << endl; // true
// ⚠️ 别把 == 写成 = !(赋值 vs 比较)
// if (a = 5) // 这是把 5 赋给 a,然后判断 a(非零即真),bug!
return 0;
}新手最大的坑:把 ==(相等比较)写成 =(赋值)。编译器会警告,但代码仍能编译,bug 很难找。建议开 -Wall 让警告变明显。
三、逻辑运算符
用于组合多个条件:
#include <iostream>
using namespace std;
int main() {
bool a = true, b = false;
cout << (a && b) << endl; // 0 逻辑与(两边都真才真)
cout << (a || b) << endl; // 1 逻辑或(一边真即真)
cout << (!b) << endl; // 1 逻辑非(取反)
// 短路求值:&& 第一个为假就不再算第二个;|| 第一个为真就不再算第二个
int x = 0;
if (x != 0 && 10/x > 1) {
// x == 0 时 && 直接短路,不会执行 10/x,避免除零崩溃
cout << "won't print" << endl;
}
// 常见用法:判断范围
int age = 25;
if (age >= 18 && age <= 60) {
cout << "劳动年龄" << endl;
}
return 0;
}- &&(逻辑与):两边都真才真。用于"同时满足"。
- ||(逻辑或):一边真即真。用于"至少一个"。
- !(逻辑非):取反。一般可以省略,如
!done比done == false简洁。 - 短路求值:
&&第一个为假就跳过第二个,||第一个为真就跳过第二个。常用于"防 null 再访问":p != nullptr && p->value > 0。
四、位运算符
位运算直接操作二进制位,底层编程、性能优化、加密、图形都缺不了:
#include <iostream>
using namespace std;
int main() {
unsigned char a = 0b1100; // 12(二进制 1100)
unsigned char b = 0b1010; // 10(二进制 1010)
cout << (int)(a & b) << endl; // 8 位与 1000
cout << (int)(a | b) << endl; // 14 位或 1110
cout << (int)(a ^ b) << endl; // 6 位异或 0110(不同为 1)
cout << (int)(~a) << endl; // 243 位取反(8 位下)
cout << (int)(a << 2) << endl; // 48 位左移 2 位(乘 4)
cout << (int)(a >> 2) << endl; // 3 位右移 2 位(除 4)
// 经典用法:权限标志位(位掩码)
const int READ = 1; // 0001
const int WRITE = 2; // 0010
const int EXEC = 4; // 0100
int perm = READ | WRITE; // 0011(可读可写)
cout << (perm & READ) << endl; // 1(有读权限)
cout << (perm & EXEC) << endl; // 0(无执行权限)
return 0;
}位运算的常见用途:
- 权限标志位(最经典):用一组 2 的幂表示权限,位或组合、位与检测。
- 性能优化:乘除 2 的幂可以用
<<>>替代(现代编译器会自动优化)。 - 图形/加密:像素颜色 RGB 用位运算提取最自然。
五、赋值运算符
赋值运算符除了基本的 =,还有一系列复合赋值:
#include <iostream>
using namespace std;
int main() {
int x = 10;
x += 5; // 等同 x = x + 5; 现在 x = 15
x -= 3; // 等同 x = x - 3; 现在 x = 12
x *= 2; // 等同 x = x * 2; 现在 x = 24
x /= 4; // 等同 x = x / 4; 现在 x = 6
x %= 4; // 等同 x = x % 4; 现在 x = 2
// 位运算复合赋值
x <<= 3; // 等同 x = x << 3; 现在 x = 16
x &= 0xF; // 等同 x = x & 15;现在 x = 16
x |= 1; // 等同 x = x | 1; 现在 x = 17
cout << x << endl; // 17
// 逗号运算符:从左到右计算,结果取最右
int y = (1, 2, 3);
cout << y << endl; // 3
return 0;
}复合赋值(+=、-=、*=...)更简洁,推荐用。
六、三元运算符
三元运算符 ?: 是"短小的 if/else",一行就能搞定简单的二选一:
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 20;
// 三元运算符:条件 ? 真值 : 假值
int max = (a > b) ? a : b;
cout << max << endl; // 20
// 等价于:
int m;
if (a > b) {
m = a;
} else {
m = b;
}
// 三元可以嵌套,但别太花哨(可读性差)
int score = 85;
string grade = (score >= 90) ? "A" :
(score >= 80) ? "B" :
(score >= 60) ? "C" : "D";
cout << grade << endl; // B
return 0;
}使用建议:简单二选一用三元,复杂逻辑用 if/else。不要嵌套太深,可读性会断崖式下降。
七、其他常用运算符
#include <iostream>
using namespace std;
int main() {
// sizeof:返回类型/变量占的字节数
cout << sizeof(int) << endl; // 4
cout << sizeof(double) << endl; // 8
// 三元 + 条件运算符
int x = 10;
cout << (x > 0 ? "positive" : "non-positive") << endl;
// 逗号运算符
int a = (1, 2, 3);
cout << a << endl; // 3
// 作用域解析 ::
int y = 5;
{
int y = 10;
cout << y << endl; // 10(局部)
cout << ::y << endl; // 5(外层)
}
// 成员访问:.(对象) ->(指针)
// 下标:[](数组/容器)
// 函数调用:() 等
return 0;
}- sizeof:查类型字节数,在写底层、跨平台代码时必备。
- 逗号:从左到右计算,结果取最右。平时用得少。
- ::(作用域解析):
类名::成员、命名空间::成员、::变量(访问全局)。 - .(成员访问):
obj.member。 - ->(指针成员访问):
ptr->member等价于(*ptr).member。 - [](下标):
arr[i]。
八、运算符优先级
C++ 有几十个运算符,优先级不必全背,但要记住几个易错的:
// 优先级从高到低(常用部分):
// 1. () [] -> . :: (作用域/成员)
// 2. ! ~ ++ -- + -(正负) * &(解引用/取址) sizeof
// 3. * / % (算术)
// 4. + - (算术)
// 5. << >> (移位)
// 6. < <= > >= (关系)
// 7. == != (关系)
// 8. & ^ | (位运算)
// 9. && (逻辑与)
// 10. || (逻辑或)
// 11. ?: (三元)
// 12. = += -= *= /= ... (赋值)
// 13. , (逗号)
// 实战建议:不确定优先级时,直接用括号!可读性最重要。
// a + b * c => 隐式是 a + (b*c)
// (a + b) * c => 必须显式加括号
// 经典坑:位运算优先级低于关系运算
// flags & MASK == 0 实际是 flags & (MASK == 0),错误!
// 应写成:(flags & MASK) == 0实用建议:写代码时,只要不是 100% 确定,就加括号。括号不会让代码变慢,但能让代码意图明确、避免 bug。
九、运算符重载(预告)
C++ 独有的强大特性:可以给自定义类型重新定义运算符的含义。比如你定义一个 Vector3(三维向量)类,可以重载 + 让 v1 + v2 做向量加法。这在 C/Java/Python 里都做不到。我们会在类与对象那章详细讲。
小结
这一章你认识了 C++ 的所有常用运算符:算术、关系、逻辑、位、赋值、三元、sizeof 等。记住了几个坑:整数除法、== vs =、位运算优先级低于关系运算。下一篇我们看控制流——怎么让程序"做判断、重复干活"。
← 上一篇 C++ 数据类型
下一篇 C++ 控制流 →