C 运算符入门
更新时间:2026-08-26。本文是
languages/c/主题入门层第 9 篇。变量有了,接下来是"怎么运算"。C 的运算符比大多数语言都多,但常用的就三类:算术、关系、逻辑。这一篇把它们连同优先级讲清楚——优先级是新手最容易写出"你以为对、其实错"代码的地方。
本文要回答的问题
5 / 2为什么等于2?怎么得到2.5?&&和||的"短路"是什么意思?a + b * c到底先算谁?
一、算术运算符
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
+ - | 加减 | 7 - 2 | 5 |
* | 乘 | 3 * 4 | 12 |
/ | 除 | 7 / 2 | 3(见下) |
% | 取余 | 7 % 2 | 1 |
-(一元) | 取负 | -x | 相反数 |
整数除法截断是第一个坑:两个整数相除,结果还是整数,小数部分直接丢掉(不是四舍五入):
int a = 7, b = 2;
double r = a / b; // r = 3.0,不是 3.5!先整数除再转 double
double r2 = (double)a / b; // r2 = 3.5,先转一个再除% 取余在循环/分组场景很常用:n % 2 判断奇偶、n % 10 取个位数。注意 % 的操作数必须是整型,浮点没有取余(用 fmod)。
二、关系运算符
| 运算符 | 含义 |
|---|---|
== | 相等(两个等号!) |
!= | 不等 |
< > <= >= | 大小比较 |
关系运算的结果是 int:成立为 1,不成立为 0。C 里没有真正的布尔类型(C99 之后有 stdbool.h 的 bool,本质还是 0/1)。
int x = 5;
printf("%d\n", x > 3); // 1
printf("%d\n", x == 4); // 0最经典的错误:if (x = 5)——一个等号是赋值,不是比较!x = 5 把 5 赋给 x,表达式值是 5(非 0,为真),所以条件永远成立。-Wall 会警告这个。赋值和相等的坑在赋值与自增自减和if-else 分支里还会遇到。
三、逻辑运算符与短路求值
| 运算符 | 含义 | 结果 |
|---|---|---|
&& | 逻辑与(AND) | 两边都为真才为真 |
| ` | ` | |
! | 逻辑非(NOT) | 取反 |
短路求值是 C 的"懒":&& 左边为假,右边根本不算;|| 左边为真,右边也不算。这不只是性能优化,还能防错:
// 用短路保护:ptr 为 NULL 时根本不会解引用
if (ptr != NULL && ptr->value > 0) {
// 安全
}
// 用短路保护除法:n 为 0 时不会执行除法
if (n != 0 && total / n > 10) {
// 安全
}如果把顺序写反成 ptr->value > 0 && ptr != NULL,NULL 解引用直接段错误。把"可能出错的检查"放前面,这是短路求值的日常用法。
四、优先级:先算谁
C 的优先级表很长,入门只需记住这个简表(从高到低):
| 优先级 | 运算符 |
|---|---|
| 高 | 括号 ()、[]、->、. |
一元:!、++、--、&、*、-(负号) | |
乘除 * / % | |
加减 + - | |
比较 < > <= >= | |
相等 == != | |
逻辑与 && | |
| 低 | 逻辑或 ` |
两个实用结论:
- 乘除优先于加减:
a + b * c是a + (b * c),跟数学一致; - 不确定就加括号。
if ((a && b) || c)比if (a && b || c)让所有人(包括三个月后的你自己)少猜一秒。加括号不是示弱,是沟通。
五、自增自减:i++ 与 ++i
int i = 1;
int a = i++; // a = 1,i 变成 2:先取原值,再自增
int j = 1;
int b = ++j; // b = 2,j 变成 2:先自增,再取新值| 写法 | 含义 | 表达式的值 |
|---|---|---|
i++ | 先返回 i,再自增 | 旧值 |
++i | 先自增,再返回 i | 新值 |
单独写 i++; 时两者没区别,多数人默认 i++。但别在同一行里对同一个变量多次自增:i = i++ + ++i; 是未定义行为(C 标准不管先算哪个),结果因编译器而异。这条规则在赋值与自增自减里细讲。
六、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| 整数除法 | 7 / 2 等于 3 | 先 (double) 转换 |
= 当 == | 条件恒真 | 开 -Wall |
| 短路顺序写反 | 解引用 NULL 崩溃 | 安全检查放左边 |
| 优先级记错 | 结果和预期不符 | 拿不准就加括号 |
| 一语句多自增 | 未定义行为 | 一条语句只改一个变量 |
七、与本站主线衔接
- 位运算符(
& | ^ ~ << >>)是下一课,见位运算符入门; - 运算符优先级与求值顺序的底层(编译器怎么生成指令),见与汇编、性能剖析衔接;
- 逻辑表达式的短路在编译器眼里是什么,见编译优化行为。
一句话总结
算术记住整数除法截断、关系记住 == 是两个等号、逻辑记住短路求值(安全检查放左边)、优先级拿不准就加括号——四类运算符,四条口诀,常用代码九成不出错。