一、课前热身:运算符是什么?
摘要:本文以大白话方式系统讲解 C 语言中的四大类运算符——算术运算符(含自增自减)、赋值运算符、关系运算符和逻辑运算符,并涵盖三目运算符、运算符优先级及短路特性。通过大量代码示例、运行结果和易错点分析,帮助初学者快速掌握运算符的用法与常见陷阱。文末附有综合计算器示例和课后练习。
想象一下,你有一个计算器。计算器上有哪些按键?数字键 0-9,还有 +、-、×、÷、= 这些符号。这些符号就是「运算符」,它们的作用就是让数字做各种运算。
C 语言里的运算符也是一样的作用——让变量和数据做运算。只不过 C 语言的运算符更多、更强大。
今天我们就学四类最常用的运算符:
- 算术运算符:加减乘除、自增自减
- 赋值运算符:把值存到变量里
- 关系运算符:比大小,判断真假
- 逻辑运算符:并且、或者、不是
💡 运算符是写程序的基础,就像学数学要先学加减乘除一样。今天内容有点多,但都不难,跟着例子走一遍就会了。
二、算术运算符
2.1 基本算术运算
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
| + | 加法 | 5 + 3 | 8 |
| - | 减法 | 5 - 3 | 2 |
| * | 乘法 | 5 * 3 | 15 |
| / | 除法 | 5 / 3 | 1(注意!整数除法) |
| % | 取余(模运算) | 5 % 3 | 2 |
#include <stdio.h>
int main() {
int a = 10, b = 3;
printf("a + b = %d\n", a + b); // 13
printf("a - b = %d\n", a - b); // 7
printf("a * b = %d\n", a * b); // 30
printf("a / b = %d\n", a / b); // 3(整数除法,只保留整数部分)
printf("a %% b = %d\n", a % b); // 1(取余数,10除以3余1)
return 0;
}
运行结果:
a + b = 13
a - b = 7
a * b = 30
a / b = 3
a % b = 1
⚠️ 重点注意:两个整数相除,结果也是整数,直接把小数部分砍掉(不是四舍五入)!5 / 3 = 1,不是 1.666,也不是 2。想要小数结果,至少有一个数是浮点数。
浮点数除法
#include <stdio.h>
int main() {
int a = 5, b = 2;
printf("整数除法:%d / %d = %d\n", a, b, a / b); // 2
printf("浮点数除法:%.1f / %d = %.2f\n", 5.0, b, 5.0 / b); // 2.50
return 0;
}
运行结果:
整数除法:5 / 2 = 2
浮点数除法:5.0 / 2 = 2.50
💡 取余运算符 % 只能用于整数,不能用于浮点数。它的用处很多,比如判断奇偶(x % 2 == 0 就是偶数)、找个位数、循环计数等等。
2.2 自增自减运算符(重点难点)
写程序的时候,经常需要让一个变量加 1 或者减 1。比如计数的时候,count = count + 1。C 语言提供了更简洁的写法:++ 和 --。
| 运算符 | 含义 | 等价于 |
|---|---|---|
| a++ | 自增(后缀) | a = a + 1(先用后加) |
| ++a | 自增(前缀) | a = a + 1(先加后用) |
| a– | 自减(后缀) | a = a - 1(先用后减) |
| –a | 自减(前缀) | a = a - 1(先减后用) |
前缀和后缀的区别
大白话解释:
a++—— 「先用再说」:先把 a 的值拿出去用,用完了再给 a 加 1++a—— 「先加再用」:先给 a 加 1,加完了再把新值拿出去用
#include <stdio.h>
int main() {
int a = 5;
int b;
// 后缀自增:先用后加
b = a++; // 先把a的值(5)赋给b,然后a变成6
printf("后缀:b=%d, a=%d\n", b, a); // b=5, a=6
// 重置a
a = 5;
// 前缀自增:先加后用
b = ++a; // 先给a加1变成6,然后把6赋给b
printf("前缀:b=%d, a=%d\n", b, a); // b=6, a=6
return 0;
}
运行结果:
后缀:b=5, a=6
前缀:b=6, a=6
💡 记忆口诀:++ 在后面,就「后」加;++ 在前面,就「前」加。或者记成:谁在前谁说了算。变量在前就先用变量,++ 在前就先自增。
⚠️ 新手容易犯的错:不要在一个表达式里写好几个 a++ 或者 ++a,比如 a++ + ++a 这种。不同编译器结果可能不一样,而且代码可读性极差。写代码要清晰,不要炫技。
自增自减的常见用法
#include <stdio.h>
int main() {
int count = 0;
// 最常见:单独使用,前缀后缀效果一样
count++;
printf("count = %d\n", count); // 1
++count;
printf("count = %d\n", count); // 2
// 用在循环里(后面会讲循环)
// for (int i = 0; i < 10; i++) { ... }
return 0;
}
💡 如果只是单独写一句 a++; 或者 ++a;,那两者效果完全一样,都是让 a 加 1。只有当自增运算和其他运算混在一起的时候,才有区别。
三、赋值运算符
3.1 基本赋值
= 就是赋值运算符,作用是把右边的值存到左边的变量里。
⚠️ 注意:C 语言里的 = 不是「等于」的意思,是「赋值」的意思!等于用 ==(两个等号)。这是新手最容易搞混的,没有之一!
int a = 5; // 把5赋值给a
a = 10; // 把10赋值给a,原来的5被覆盖了
3.2 复合赋值运算符
如果要让变量自己和自己运算,比如 a = a + 5,可以简写为 a += 5。
| 运算符 | 含义 | 等价于 |
|---|---|---|
| += | 加等于 | a += b → a = a + b |
| -= | 减等于 | a -= b → a = a - b |
| *= | 乘等于 | a *= b → a = a * b |
| /= | 除等于 | a /= b → a = a / b |
| %= | 取余等于 | a %= b → a = a % b |
#include <stdio.h>
int main() {
int a = 10;
a += 5; // 等价于 a = a + 5
printf("a += 5 后:%d\n", a); // 15
a -= 3; // 等价于 a = a - 3
printf("a -= 3 后:%d\n", a); // 12
a *= 2; // 等价于 a = a * 2
printf("a *= 2 后:%d\n", a); // 24
a /= 4; // 等价于 a = a / 4
printf("a /= 4 后:%d\n", a); // 6
a %= 4; // 等价于 a = a % 4
printf("a %%= 4 后:%d\n", a); // 2
return 0;
}
运行结果:
a += 5 后:15
a -= 3 后:12
a *= 2 后:24
a /= 4 后:6
a %= 4 后:2
💡 复合赋值运算符不仅写起来简洁,编译后的执行效率也可能更高(因为只计算一次左边的地址)。推荐能用就用。
四、关系运算符
4.1 什么是关系运算?
关系运算就是「比大小」,判断两个数的关系。关系运算的结果只有两种:真(成立)或者假(不成立)。
在 C 语言里,「真」用非 0 的数表示(通常是 1),「假」用 0 表示。
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
| > | 大于 | 5 > 3 | 1(真) |
| < | 小于 | 5 < 3 | 0(假) |
| >= | 大于等于 | 5 >= 5 | 1(真) |
| <= | 小于等于 | 5 <= 3 | 0(假) |
| == | 等于 | 5 == 5 | 1(真) |
| != | 不等于 | 5 != 3 | 1(真) |
#include <stdio.h>
int main() {
int a = 5, b = 3;
printf("%d > %d = %d\n", a, b, a > b); // 1
printf("%d < %d = %d\n", a, b, a < b); // 0
printf("%d >= %d = %d\n", a, b, a >= b); // 1
printf("%d <= %d = %d\n", a, b, a <= b); // 0
printf("%d == %d = %d\n", a, b, a == b); // 0
printf("%d != %d = %d\n", a, b, a != b); // 1
return 0;
}
运行结果:
5 > 3 = 1
5 < 3 = 0
5 >= 3 = 1
5 <= 3 = 0
5 == 3 = 0
5 != 3 = 1
⚠️ 超级重点:判断相等要用 ==(两个等号),不是 =(一个等号)!= 是赋值,== 才是判断相等。写反了程序不会报错,但逻辑完全错了,而且很难发现!
新手最容易犯的错误
// ❌ 错误写法:用了赋值号
if (a = 5) {
// 这里永远为真!因为a=5的值是5,非0就是真
// 而且a的值被改成了5
}
// ✅ 正确写法:用两个等号
if (a == 5) {
// 只有a等于5的时候才会执行这里
}
💡 小技巧:判断常量和变量是否相等时,可以把常量写在左边,比如 5 == a。这样如果你不小心写成了 5 = a,编译器会直接报错,因为不能给常量赋值。这是一个防错小技巧。
五、逻辑运算符
5.1 三种逻辑运算
逻辑运算就是「并且」「或者」「不是」的意思,用来组合多个条件。
| 运算符 | 含义 | 大白话 | 示例 |
|---|---|---|---|
| && | 逻辑与(并且) | 两边都为真,结果才为真 | a > 0 && a < 10 |
| || | 逻辑或(或者) | 只要有一边为真,结果就为真 | a < 0 || a > 10 |
| ! | 逻辑非(取反) | 真变假,假变真 | !(a > 5) |
逻辑与 &&(并且)
#include <stdio.h>
int main() {
int score = 85;
// 判断分数是否在80到90之间
if (score >= 80 && score < 90) {
printf("良好\n");
}
// 注意:不能写成 80 <= score < 90,那是数学写法,C语言里不对!
return 0;
}
逻辑或 ||(或者)
#include <stdio.h>
int main() {
int age = 65;
// 判断是否是老人或小孩
if (age < 6 || age >= 60) {
printf("可以半价\n");
}
return 0;
}
逻辑非 !(取反)
#include <stdio.h>
int main() {
int is_raining = 0; // 0表示没下雨
if (!is_raining) {
printf("没下雨,出去玩吧!\n");
}
return 0;
}
5.2 短路特性(重点!)
逻辑运算符有一个很重要的特性:短路求值。大白话就是:如果左边已经能确定结果了,右边就不执行了。
&&短路:左边为假时,右边不执行(因为已经知道结果是假了)||短路:左边为真时,右边不执行(因为已经知道结果是真了)
#include <stdio.h>
int main() {
int a = 5, b = 0;
// && 短路:左边为假,右边不执行
if (a > 10 && (b = 100)) {
printf("条件成立\n");
}
printf("b = %d\n", b); // b还是0,因为右边没执行
// || 短路:左边为真,右边不执行
a = 5;
b = 0;
if (a > 0 || (b = 100)) {
printf("条件成立\n");
}
printf("b = %d\n", b); // b还是0,因为右边没执行
return 0;
}
运行结果:
b = 0
条件成立
b = 0
💡 短路特性有好有坏:好处是效率高,不用白做功;坏处是如果右边有赋值、自增等副作用,可能不会执行。写代码的时候要注意,不要把重要的操作写在逻辑运算符的右边。
六、三目运算符(条件运算符)
6.1 什么是三目运算符?
三目运算符是 C 语言里唯一的一个有三个操作数的运算符,也叫条件运算符。它可以看作是简化版的 if-else。
语法:
条件 ? 表达式1 : 表达式2
执行逻辑:
- 如果条件为真,整个表达式的值就是表达式1的值
- 如果条件为假,整个表达式的值就是表达式2的值
#include <stdio.h>
int main() {
int score = 75;
char *result;
// 用三目运算符判断是否及格
result = (score >= 60) ? "及格" : "不及格";
printf("分数:%d,结果:%s\n", score, result);
// 等价于下面的if-else
if (score >= 60) {
result = "及格";
} else {
result = "不及格";
}
return 0;
}
运行结果:
分数:75,结果:及格
求两个数的最大值
#include <stdio.h>
int main() {
int a = 10, b = 20;
int max;
// 三目运算符求最大值
max = (a > b) ? a : b;
printf("max = %d\n", max); // 20
// 也可以直接用在printf里
printf("较大的数是:%d\n", (a > b) ? a : b);
return 0;
}
💡 三目运算符适合简单的二选一情况,写起来很简洁。但如果逻辑复杂,还是用 if-else 更清晰。代码首先要让人看懂,不要为了炫技写复杂的三目运算。
三目运算符嵌套(了解即可)
#include <stdio.h>
int main() {
int score = 85;
// 嵌套三目运算符:判断优秀、良好、及格、不及格
printf("等级:");
printf(score >= 90 ? "优秀" :
score >= 80 ? "良好" :
score >= 60 ? "及格" : "不及格");
printf("\n");
return 0;
}
运行结果:
等级:良好
⚠️ 三目运算符嵌套可读性很差,不推荐使用。复杂的判断还是用 if-else if-else 更清楚。
七、运算符优先级
7.1 优先级表格
运算符有优先级,就像数学里先乘除后加减一样。C 语言里运算符很多,优先级也分好多级。不用全记住,常用的记住就行。
| 优先级 | 运算符 | 说明 | 结合方向 |
|---|---|---|---|
| 1(最高) | () [] -> . | 括号、数组、结构体成员 | 从左到右 |
| 2 | ! ~ ++ – + - * & sizeof | 单目运算符 | 从右到左 |
| 3 | * / % | 乘、除、取余 | 从左到右 |
| 4 | + - | 加、减 | 从左到右 |
| 5 | << >> | 位移(后面讲) | 从左到右 |
| 6 | < <= > >= | 关系运算 | 从左到右 |
| 7 | == != | 等于、不等于 | 从左到右 |
| 8 | & | 按位与 | 从左到右 |
| 9 | ^ | 按位异或 | 从左到右 |
| 10 | | | 按位或 | 从左到右 |
| 11 | && | 逻辑与 | 从左到右 |
| 12 | || | 逻辑或 | 从左到右 |
| 13 | ?: | 三目运算符 | 从右到左 |
| 14 | = += -= *= /= %= | 赋值运算符 | 从右到左 |
| 15(最低) | , | 逗号运算符 | 从左到右 |
💡 不用全背!记住几个关键的就行:括号最高,然后单目运算符,然后乘除,然后加减,然后关系,然后逻辑,最后赋值。实在不确定就加括号,括号永远是最高优先级。
7.2 优先级示例
#include <stdio.h>
int main() {
int a = 5 + 3 * 2; // 先乘后加:5 + 6 = 11
printf("5 + 3 * 2 = %d\n", a);
int b = (5 + 3) * 2; // 括号优先:8 * 2 = 16
printf("(5 + 3) * 2 = %d\n", b);
int c = 10 > 5 && 3 < 4; // 先关系,后逻辑:1 && 1 = 1
printf("10 > 5 && 3 < 4 = %d\n", c);
int x = 5;
int y = -x++; // 先++(后缀),再取负?不对!
// 实际上:后缀++优先级比负号高,但后缀是「先用后加」
// 所以:-x++ 等价于 -(x++),先取x的值5取负得-5,然后x变成6
printf("y = %d, x = %d\n", y, x); // y = -5, x = 6
return 0;
}
运行结果:
5 + 3 * 2 = 11
(5 + 3) * 2 = 16
10 > 5 && 3 < 4 = 1
y = -5, x = 6
💡 最佳实践:不确定优先级就加括号!括号不仅能保证正确,还能让代码更清晰,别人一看就知道你的意图。代码是写给人看的,顺便给机器执行。
八、新手高频易错点
易错点1:== 和 = 搞混
// ❌ 错误:把赋值当判断
if (a = 5) {
// 永远为真,而且a被改成5了
}
// ✅ 正确:两个等号才是判断相等
if (a == 5) {
// 只有a等于5才执行
}
⚠️ 这是新手最最最容易犯的错误,而且编译器不报错!写完判断条件一定要检查:是不是两个等号?
易错点2:整数除法的坑
// ❌ 错误:以为会得到小数
int a = 5, b = 2;
double c = a / b; // c = 2.0,不是2.5!
// 因为a和b都是int,先做整数除法得2,再转成double
// ✅ 正确:至少有一个是浮点数
double c = (double)a / b; // 或者 5.0 / 2
// 先把a转成double,再做除法,结果是2.5
易错点3:自增自减搞反前后缀
int a = 5;
int b = a++; // 后缀:先用后加
// b = 5, a = 6
int c = 5;
int d = ++c; // 前缀:先加后用
// d = 6, c = 6
💡 记忆方法:谁在前谁说了算。变量在前就先用变量的值,++ 在前就先自增。
易错点4:逻辑运算符的短路
int a = 5, b = 0;
if (a > 10 && ++b) { // 左边为假,右边不执行
// ...
}
// b还是0,没有自增!
// 不要在逻辑运算符右边写有副作用的代码
易错点5:连续比较的写法
// ❌ 错误:数学写法直接搬过来
if (0 < a < 10) {
// 这个写法语法没错,但意思不对!
// 先算 0 < a 得0或1,再用结果和10比
// 永远为真,因为0和1都小于10
}
// ✅ 正确:用逻辑与连接
if (a > 0 && a < 10) {
// 这才是判断a是否在0到10之间
}
易错点6:取余运算的正负号
// 取余结果的符号和被除数相同
printf("%d\n", 5 % 3); // 2
printf("%d\n", -5 % 3); // -2(和被除数-5同号)
printf("%d\n", 5 % -3); // 2(和被除数5同号)
printf("%d\n", -5 % -3); // -2
💡 不同语言取余的规则可能不一样,C 语言里是「结果符号和被除数相同」。判断奇偶的时候要注意负数。
九、综合示例:简单计算器
学了这么多运算符,我们来写一个简单的计算器程序,把今天学的知识都用上:
#include <stdio.h>
int main() {
double num1, num2;
char op;
printf("===== 简单计算器 =====\n");
printf("请输入算式(如:5 + 3):");
scanf("%lf %c %lf", &num1, &op, &num2);
printf("\n计算结果:\n");
// 用三目运算符判断并输出结果
if (op == '+') {
printf("%.2f + %.2f = %.2f\n", num1, num2, num1 + num2);
} else if (op == '-') {
printf("%.2f - %.2f = %.2f\n", num1, num2, num1 - num2);
} else if (op == '*') {
printf("%.2f * %.2f = %.2f\n", num1, num2, num1 * num2);
} else if (op == '/') {
// 判断除数是否为0
if (num2 == 0) {
printf("错误:除数不能为0!\n");
} else {
printf("%.2f / %.2f = %.2f\n", num1, num2, num1 / num2);
}
} else if (op == '%') {
// 取余只能用于整数
int n1 = (int)num1;
int n2 = (int)num2;
if (n2 == 0) {
printf("错误:除数不能为0!\n");
} else {
printf("%d %% %d = %d\n", n1, n2, n1 % n2);
}
} else {
printf("错误:不支持的运算符 %c\n", op);
}
// 自增自减演示
int count = 0;
count++;
printf("\n运算次数:%d次\n", count);
return 0;
}
运行示例:
===== 简单计算器 =====
请输入算式(如:5 + 3):【10 / 4】回车
计算结果:
10.00 / 4.00 = 2.50
运算次数:1次
十、课后总结
10.1 核心知识点回顾
| 分类 | 运算符 | 关键点 |
|---|---|---|
| 算术 | + - * / % | 整数除法只保留整数,%取余只能用于整数 |
| 自增自减 | ++ – | 后缀先用后加,前缀先加后用 |
| 赋值 | = += -= *= /= %= | 右边的值存到左边,复合赋值更简洁 |
| 关系 | > < >= <= == != | 结果是0或1,==是判断,=是赋值 |
| 逻辑 | && || ! | &&两边都真才真,||一边真就真,!取反 |
| 短路 | && || | 左边能确定结果时,右边不执行 |
| 三目 | ?: | 条件?值1:值2,简化版if-else |
| 优先级 | — | 括号 > 单目 > 乘除 > 加减 > 关系 > 逻辑 > 赋值 |
10.2 六大易错点速查
- ❌
==和=搞混 —— 判断相等一定要两个等号 - ❌ 整数除法得小数 —— 至少一个浮点数才能得到小数结果
- ❌ 自增前后缀搞反 —— 谁在前谁说了算
- ❌ 逻辑运算符右边有副作用 —— 可能因为短路不执行
- ❌ 连续比较
0 < a < 10—— 要用&&连接 - ❌ 取余符号搞不清 —— 结果符号和被除数相同
10.3 课后练习
- 写一个程序,输入两个整数,输出它们的和、差、积、商、余数
- 输入一个整数,判断它是奇数还是偶数(用%运算符)
- 用三目运算符实现:输入三个整数,输出最大值
- 写一段代码验证自增自减的前缀后缀区别,自己动手跑一遍
- 故意犯几个今天讲的易错点,看看程序会出什么问题(加深印象)
—— 课时6 结束 ——
下节课预告:选择结构 if / switch
640

被折叠的 条评论
为什么被折叠?



