第 5 天:C 语言运算符与表达式 —— 数据处理的工具集
目录
🌷前言:
一、运算符与表达式的基本概念
二、算术运算符
2.1 基本算术运算符
2.2 算术运算符的优先级与结合性
三、赋值运算符
3.1 基本赋值运算符
3.2 复合赋值运算符
四、关系运算符
4.1 关系运算符列表
五、逻辑运算符
5.1 逻辑运算符列表
5.2 短路求值特性
六、自增自减运算符
6.1 自增自减运算符的两种形式
6.2 使用注意事项
七、条件运算符
7.1 条件运算符的语法
7.2 条件运算符与 if 语句的比较
八、逗号运算符
8.1 逗号运算符的使用
九、运算符优先级与结合性总结
9.1 常用运算符优先级表(从高到低)
9.2 优先级示例解析
十、扩展练习
10.1 练习 1:简单计算器
10.2 练习 2:学生成绩评级
十一、总结与常见问题解答
11.1 核心知识点回顾
11.2 常见问题解答
🌈共勉:
🌷前言:
在上一篇学习中,我们系统掌握了 C 语言的基本数据类型,包括整型、浮点型和字符型的定义、特性及使用场景。我们了解了不同类型数据的存储方式、取值范围和精度特点,也学会了根据实际需求选择合适的数据类型。这些知识让我们能够正确地定义和存储各种数据,为程序处理信息奠定了基础。
今天,我们将学习 C 语言中用于处理数据的工具 —— 运算符与表达式。如果说数据类型是程序的 "原材料",那么运算符就是 "加工工具",而表达式则是 "加工方法"。掌握运算符和表达式的使用,能让我们对数据进行各种计算和处理,实现程序的核心逻辑功能。
一、运算符与表达式的基本概念
运算符(Operator)是一种特殊的符号,用于告诉编译器执行特定的数学或逻辑操作。表达式(Expression)则是由运算符和操作数(变量、常量等)组成的式子。
例如:a + b * c
是一个表达式,其中 +
和 *
是运算符,a
、b
、c
是操作数。
C 语言的运算符非常丰富,可分为以下几类:
- 算术运算符
- 赋值运算符
- 关系运算符
- 逻辑运算符
- 自增自减运算符
- 条件运算符
- 逗号运算符
- 位运算符(高级主题,后续介绍)
- 指针运算符(高级主题,后续介绍)
表达式的运算结果具有特定的数据类型,称为表达式的类型。例如,两个 int 类型变量相加的表达式,其结果仍为 int 类型。
二、算术运算符
算术运算符用于执行基本的数学运算,如加、减、乘、除等。
2.1 基本算术运算符
运算符 | 名称 | 示例 | 说明 |
---|---|---|---|
+ | 加法 | a + b | 求 a 与 b 的和 |
- | 减法 | a - b | 求 a 与 b 的差 |
* | 乘法 | a * b | 求 a 与 b 的积 |
/ | 除法 | a / b | 求 a 与 b 的商 |
% | 取余(模运算) | a % b | 求 a 除以 b 的余数 |
使用示例:
c
运行
#include <stdio.h>int main() {int a = 10, b = 3;float c = 10.0f, d = 3.0f;// 整数运算printf("整数运算:\n");printf("%d + %d = %d\n", a, b, a + b);printf("%d - %d = %d\n", a, b, a - b);printf("%d * %d = %d\n", a, b, a * b);printf("%d / %d = %d\n", a, b, a / b); // 整数除法,结果取整printf("%d %% %d = %d\n", a, b, a % b); // 取余运算,注意格式符用%%// 浮点数运算printf("\n浮点数运算:\n");printf("%.1f + %.1f = %.1f\n", c, d, c + d);printf("%.1f - %.1f = %.1f\n", c, d, c - d);printf("%.1f * %.1f = %.1f\n", c, d, c * d);printf("%.1f / %.1f = %.1f\n", c, d, c / d); // 浮点数除法,保留小数return 0;
}
输出结果:
plaintext
整数运算:
10 + 3 = 13
10 - 3 = 7
10 * 3 = 30
10 / 3 = 3
10 % 3 = 1浮点数运算:
10.0 + 3.0 = 13.0
10.0 - 3.0 = 7.0
10.0 * 3.0 = 30.0
10.0 / 3.0 = 3.3
注意事项:
- 整数除法会自动舍弃小数部分,只保留整数部分(不是四舍五入)
- 取余运算
%
仅适用于整数,不能用于浮点数 - 除数不能为 0,否则会导致程序运行错误
2.2 算术运算符的优先级与结合性
当一个表达式中包含多个运算符时,需要遵循一定的运算顺序:
- 先乘除,后加减(
*
、/
、%
优先级高于+
、-
) - 同级运算符从左到右依次计算(左结合性)
- 可以使用括号
()
改变运算顺序,括号内的运算优先执行
优先级示例:
c
运行
#include <stdio.h>int main() {int x = 10, y = 3, z = 2;// 不同优先级的运算int result1 = x + y * z; // 先乘后加int result2 = (x + y) * z; // 括号改变优先级// 同级运算(左结合)int result3 = x / y * z; // 先除后乘int result4 = x * y / z; // 先乘后除printf("10 + 3 * 2 = %d\n", result1);printf("(10 + 3) * 2 = %d\n", result2);printf("10 / 3 * 2 = %d\n", result3);printf("10 * 3 / 2 = %d\n", result4);return 0;
}
输出结果:
plaintext
10 + 3 * 2 = 16
(10 + 3) * 2 = 26
10 / 3 * 2 = 6
10 * 3 / 2 = 15
三、赋值运算符
赋值运算符用于将一个值赋给变量,最基本的赋值运算符是=
。
3.1 基本赋值运算符
基本赋值运算符的语法:
c
运行
变量 = 表达式;
功能:计算右边表达式的值,然后将其赋给左边的变量。
示例:
c
运行
int a, b;
a = 10; // 将常量10赋给变量a
b = a + 5; // 将表达式a+5的结果赋给变量b
3.2 复合赋值运算符
C 语言提供了多种复合赋值运算符,将算术运算和赋值运算结合起来,使代码更简洁。
复合运算符 | 等价表达式 | 说明 |
---|---|---|
+= | 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 | 取余赋值 |
使用示例:
c
运行
#include <stdio.h>int main() {int a = 10;printf("初始值: a = %d\n", a);a += 5; // 等价于 a = a + 5printf("a += 5 后: a = %d\n", a);a -= 3; // 等价于 a = a - 3printf("a -= 3 后: a = %d\n", a);a *= 2; // 等价于 a = a * 2printf("a *= 2 后: a = %d\n", a);a /= 4; // 等价于 a = a / 4printf("a /= 4 后: a = %d\n", a);a %= 3; // 等价于 a = a % 3printf("a %%= 3 后: a = %d\n", a);return 0;
}
输出结果:
plaintext
初始值: a = 10
a += 5 后: a = 15
a -= 3 后: a = 12
a *= 2 后: a = 24
a /= 4 后: a = 6
a %= 3 后: a = 0
注意:复合赋值运算符右边的表达式会作为一个整体参与运算,例如 a *= b + c
等价于 a = a * (b + c)
,而不是 a = a * b + c
。
四、关系运算符
关系运算符用于比较两个值的大小关系,运算结果是一个逻辑值(真或假)。在 C 语言中,用1
表示真,0
表示假。
4.1 关系运算符列表
运算符 | 名称 | 示例 | 说明 |
---|---|---|---|
== | 等于 | a == b | 判断 a 是否等于 b |
!= | 不等于 | a != b | 判断 a 是否不等于 b |
> | 大于 | a > b | 判断 a 是否大于 b |
< | 小于 | a < b | 判断 a 是否小于 b |
>= | 大于等于 | a >= b | 判断 a 是否大于或等于 b |
<= | 小于等于 | a <= b | 判断 a 是否小于或等于 b |
使用示例:
c
运行
#include <stdio.h>int main() {int a = 5, b = 10;printf("a = %d, b = %d\n", a, b);printf("a == b: %d\n", a == b); // 等于printf("a != b: %d\n", a != b); // 不等于printf("a > b: %d\n", a > b); // 大于printf("a < b: %d\n", a < b); // 小于printf("a >= b: %d\n", a >= b); // 大于等于printf("a <= b: %d\n", a <= b); // 小于等于// 关系表达式可以作为条件if (a < b) {printf("a小于b\n");}return 0;
}
输出结果:
plaintext
a = 5, b = 10
a == b: 0
a != b: 1
a > b: 0
a < b: 1
a >= b: 0
a <= b: 1
a小于b
注意事项:
- 不要混淆赋值运算符
=
和等于运算符==
,这是初学者常见的错误 - 关系运算符的优先级低于算术运算符,例如
a + b > c
等价于(a + b) > c
- 关系运算符的结果只能是
0
(假)或1
(真)
五、逻辑运算符
逻辑运算符用于对逻辑值进行操作,实现更复杂的逻辑判断。C 语言中的逻辑运算符有三个:与(&&)、或(||)、非(!)。
5.1 逻辑运算符列表
运算符 | 名称 | 示例 | 说明 | ||||
---|---|---|---|---|---|---|---|
&& | 逻辑与 | a && b | 当 a 和 b 都为真时,结果为真;否则为假 | ||||
逻辑或 | a | b | 当 a 或 b 为真时,结果为真;都为假时结果为假 | ||||
! | 逻辑非 | !a | 当 a 为真时,结果为假;当 a 为假时,结果为真 |
逻辑运算真值表:
| a | b | a && b | a || b | !a ||---|---|--------|--------|----|| 0 | 0 | 0 | 0 | 1 || 0 | 1 | 0 | 1 | 1 || 1 | 0 | 0 | 1 | 0 || 1 | 1 | 1 | 1 | 0 |
使用示例:
c
运行
#include <stdio.h>int main() {int a = 5, b = 10, c = 15;// 逻辑与运算printf("a < b && b < c: %d\n", a < b && b < c); // 真 && 真 = 真printf("a < b && b > c: %d\n", a < b && b > c); // 真 && 假 = 假// 逻辑或运算printf("a > b || b < c: %d\n", a > b || b < c); // 假 || 真 = 真printf("a > b || b > c: %d\n", a > b || b > c); // 假 || 假 = 假// 逻辑非运算printf("!(a < b): %d\n", !(a < b)); // 非真 = 假printf("!(a > b): %d\n", !(a > b)); // 非假 = 真return 0;
}
输出结果:
plaintext
a < b && b < c: 1
a < b && b > c: 0
a > b || b < c: 1
a > b || b > c: 0
!(a < b): 0
!(a > b): 1
5.2 短路求值特性
C 语言的逻辑运算符具有短路求值(short-circuit evaluation)特性:
- 对于
a && b
,如果 a 为假,则不再计算 b(因为结果已经确定为假) - 对于
a || b
,如果 a 为真,则不再计算 b(因为结果已经确定为真)
短路求值示例:
c
运行
#include <stdio.h>int main() {int x = 5, y = 5;// 逻辑与的短路特性printf("逻辑与短路测试:\n");(x == 6) && (y = 10); // x==6为假,后面的y=10不会执行printf("x = %d, y = %d\n", x, y); // y仍然是5// 逻辑或的短路特性printf("\n逻辑或短路测试:\n");(x == 5) || (y = 10); // x==5为真,后面的y=10不会执行printf("x = %d, y = %d\n", x, y); // y仍然是5return 0;
}
输出结果:
plaintext
逻辑与短路测试:
x = 5, y = 5逻辑或短路测试:
x = 5, y = 5
六、自增自减运算符
自增(++)和自减(--)运算符是 C 语言中特有的运算符,用于将变量的值加 1 或减 1。
6.1 自增自减运算符的两种形式
运算符 | 名称 | 前缀形式 | 后缀形式 |
---|---|---|---|
++ | 自增 | ++a | a++ |
-- | 自减 | --a | a-- |
- 前缀形式(++a):先将 a 的值加 1,再使用 a 的值
- 后缀形式(a++):先使用 a 的值,再将 a 的值加 1
使用示例:
c
运行
#include <stdio.h>int main() {int a = 5, b = 5;int result1, result2;// 自增运算符result1 = ++a; // 前缀形式:先加1,再赋值printf("前缀自增: a = %d, result1 = %d\n", a, result1);result2 = b++; // 后缀形式:先赋值,再加1printf("后缀自增: b = %d, result2 = %d\n", b, result2);// 自减运算符int c = 5, d = 5;int result3, result4;result3 = --c; // 前缀形式:先减1,再赋值printf("前缀自减: c = %d, result3 = %d\n", c, result3);result4 = d--; // 后缀形式:先赋值,再减1printf("后缀自减: d = %d, result4 = %d\n", d, result4);return 0;
}
输出结果:
plaintext
前缀自增: a = 6, result1 = 6
后缀自增: b = 6, result2 = 5
前缀自减: c = 4, result3 = 4
后缀自减: d = 4, result4 = 5
6.2 使用注意事项
-
自增自减运算符只能用于变量,不能用于常量或表达式,例如
5++
或(a + b)++
都是错误的 -
避免在一个表达式中多次使用自增自减运算符,这会导致代码可读性差且可能产生未定义行为
不推荐的写法:
c
运行
int x = 5, y; y = x++ + ++x; // 行为未定义,不同编译器可能有不同结果
七、条件运算符
条件运算符(?:)是 C 语言中唯一的三目运算符,它根据条件的真假返回两个值中的一个。
7.1 条件运算符的语法
c
运行
条件表达式 ? 表达式1 : 表达式2;
功能:
- 如果条件表达式为真(非 0),则整个表达式的值为表达式 1 的值
- 如果条件表达式为假(0),则整个表达式的值为表达式 2 的值
使用示例:
c
运行
#include <stdio.h>int main() {int a = 10, b = 20;int max, min;// 使用条件运算符求最大值max = (a > b) ? a : b;printf("%d和%d中的最大值是%d\n", a, b, max);// 使用条件运算符求最小值min = (a < b) ? a : b;printf("%d和%d中的最小值是%d\n", a, b, min);// 条件运算符嵌套int c = 15;int largest = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);printf("%d、%d和%d中的最大值是%d\n", a, b, c, largest);// 与printf结合使用printf("a%s大于b\n", (a > b) ? "" : "不");return 0;
}
输出结果:
plaintext
10和20中的最大值是20
10和20中的最小值是10
10、20和15中的最大值是20
a不大于b
7.2 条件运算符与 if 语句的比较
条件运算符可以实现简单的条件判断,与 if 语句相比:
- 条件运算符是一个表达式,有返回值
- if 语句是一种控制结构,没有返回值
- 简单的条件判断用条件运算符更简洁,复杂的条件判断用 if 语句更清晰
例如,以下两段代码功能相同:
使用条件运算符:
c
运行
max = (a > b) ? a : b;
使用 if 语句:
c
运行
if (a > b) {max = a;
} else {max = b;
}
八、逗号运算符
逗号运算符(,)用于将多个表达式连接成一个表达式,整个表达式的值是最后一个表达式的值。
8.1 逗号运算符的使用
c
运行
表达式1, 表达式2, ..., 表达式n
功能:按顺序执行每个表达式,整个逗号表达式的值是最后一个表达式的值。
使用示例:
c
运行
#include <stdio.h>int main() {int a, b, c;// 逗号表达式用于初始化多个变量a = 1, b = 2, c = 3;printf("a = %d, b = %d, c = %d\n", a, b, c);// 逗号表达式作为赋值操作数int result = (a += 5, b *= 2, c + 10);printf("执行逗号表达式后: a = %d, b = %d, c = %d\n", a, b, c);printf("逗号表达式的结果: %d\n", result);// 逗号表达式在for循环中的应用printf("\n使用逗号表达式的循环:\n");for (int i = 0, j = 10; i < 5; i++, j--) {printf("i = %d, j = %d\n", i, j);}return 0;
}
输出结果:
plaintext
a = 1, b = 2, c = 3
执行逗号表达式后: a = 6, b = 4, c = 3
逗号表达式的结果: 13使用逗号表达式的循环:
i = 0, j = 10
i = 1, j = 9
i = 2, j = 8
i = 3, j = 7
i = 4, j = 6
注意:逗号运算符的优先级是所有运算符中最低的,因此在许多情况下需要使用括号来改变优先级。
九、运算符优先级与结合性总结
当一个表达式中包含多种运算符时,运算顺序由运算符的优先级和结合性决定。
9.1 常用运算符优先级表(从高到低)
优先级 | 运算符 | 结合性 |
---|---|---|
1 | ()、[]、->、. | 左到右 |
2 | !、~、++、--、+(正)、-(负)、*(指针)、&(取地址)、sizeof | 右到左 |
3 | *、/、% | 左到右 |
4 | +、- | 左到右 |
5 | <<、>> | 左到右 |
6 | <、<=、>、>= | 左到右 |
7 | ==、!= | 左到右 |
8 | & | 左到右 |
9 | ^ | 左到右 |
10 | | | 左到右 |
11 | && | 左到右 |
12 | || | 左到右 |
13 | ?: | 右到左 |
14 | =、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>= | 右到左 |
15 | , | 左到右 |
9.2 优先级示例解析
c
运行
#include <stdio.h>int main() {int a = 2, b = 3, c = 4, d = 5;int result;// 综合表达式示例result = a + b * c - d / a;printf("a + b * c - d / a = %d\n", result);// 运算顺序: b*c → d/a → a+结果1 → 结果3-结果2 → 最终结果// 使用括号改变优先级result = (a + b) * (c - d) / a;printf("(a + b) * (c - d) / a = %d\n", result);// 包含逻辑运算符的表达式int x = 5, y = 10;int flag = x > 3 && y++ < 11;printf("flag = %d, y = %d\n", flag, y);// 运算顺序: x>3 → y++<11 → 逻辑与运算return 0;
}
输出结果:
plaintext
a + b * c - d / a = 2 + 12 - 2 = 12
(a + b) * (c - d) / a = 5 * (-1) / 2 = -2
flag = 1, y = 11
建议:当对运算符优先级不确定时,使用括号明确指定运算顺序,这可以提高代码的可读性。
十、扩展练习
10.1 练习 1:简单计算器
编写程序,实现两个数的加、减、乘、除运算。
c
运行
#include <stdio.h>int main() {float num1, num2;char op;printf("请输入表达式(格式:数字 运算符 数字): ");scanf("%f %c %f", &num1, &op, &num2);switch(op) {case '+':printf("%.2f + %.2f = %.2f\n", num1, num2, num1 + num2);break;case '-':printf("%.2f - %.2f = %.2f\n", num1, num2, num1 - num2);break;case '*':printf("%.2f * %.2f = %.2f\n", num1, num2, num1 * num2);break;case '/':if (num2 == 0) {printf("错误:除数不能为0\n");} else {printf("%.2f / %.2f = %.2f\n", num1, num2, num1 / num2);}break;default:printf("错误:未知运算符\n");}return 0;
}
运行示例:
plaintext
请输入表达式(格式:数字 运算符 数字): 10 + 5.5
10.00 + 5.50 = 15.50
10.2 练习 2:学生成绩评级
编写程序,根据学生成绩(0-100)评定等级:90-100 为 A,80-89 为 B,70-79 为 C,60-69 为 D,0-59 为 E。
c
运行
#include <stdio.h>int main() {float score;char grade;printf("请输入学生成绩(0-100): ");scanf("%f", &score);// 检查成绩是否在有效范围内if (score < 0 || score > 100) {printf("成绩无效!\n");return 0;}// 使用条件运算符评定等级grade = (score >= 90) ? 'A' :(score >= 80) ? 'B' :(score >= 70) ? 'C' :(score >= 60) ? 'D' : 'E';printf("成绩等级: %c\n", grade);return 0;
}
运行示例:
plaintext
请输入学生成绩(0-100): 85
成绩等级: B
十一、总结与常见问题解答
11.1 核心知识点回顾
- 运算符是用于执行特定操作的符号,表达式是由运算符和操作数组成的式子
- 算术运算符用于基本数学运算,包括 +、-、*、/、%
- 赋值运算符用于给变量赋值,基本形式为 =,还有多种复合赋值形式
- 关系运算符用于比较两个值的大小,结果为 0(假)或 1(真)
- 逻辑运算符用于逻辑判断,包括 &&(与)、||(或)、!(非),具有短路求值特性
- 自增自减运算符(++、--)用于将变量值加 1 或减 1,有前缀和后缀两种形式
- 条件运算符(?:)是三目运算符,根据条件返回不同的值
- 逗号运算符用于将多个表达式组合成一个,结果为最后一个表达式的值
- 运算符的优先级和结合性决定了表达式的运算顺序
11.2 常见问题解答
Q1:为什么 10 / 3 的结果是 3 而不是 3.333?
A1:因为在 C 语言中,两个整数相除的结果还是整数,会自动舍弃小数部分(不是四舍五入)。如果需要得到浮点型结果,至少要将其中一个操作数改为浮点型,例如 10.0 / 3 或 10 / 3.0。
Q2:= 和 == 有什么区别?
A2:= 是赋值运算符,用于将右边的值赋给左边的变量;== 是关系运算符,用于判断左右两边的值是否相等。这是初学者最容易混淆的两个运算符,例如 if (a = 5) 是错误的,正确的应该是 if (a == 5)。
Q3:什么是短路求值?有什么实际应用?
A3:短路求值是逻辑运算符的特性:对于 a && b,如果 a 为假则不计算 b;对于 a || b,如果 a 为真则不计算 b。实际应用中,可以利用这一特性避免一些错误,例如:
c
运行
if (ptr != NULL && ptr->value > 0) { ... }
这里如果 ptr 为 NULL,就不会执行 ptr->value 的访问,避免了空指针错误。
Q4:在一个表达式中多次使用自增运算符会有什么问题?
A4:在一个表达式中多次使用自增运算符(如 a++ + ++a)会导致未定义行为,不同的编译器可能会有不同的处理方式,得到不同的结果。为了代码的可读性和正确性,应避免这种写法
🌟个人主页:编程攻城狮
🌟人生格言:得知坦然 ,失之淡然
🌈共勉:
今天我们学习了 C 语言中丰富的运算符和表达式,它们是处理数据的重要工具。掌握这些运算符的使用方法和优先级规则,能让我们灵活地处理各种数据,实现复杂的计算和逻辑判断。
在下一篇内容中,我们将学习 C 语言的流程控制语句,包括 if-else 条件语句和 switch 多分支语句。这些语句能让程序根据不同的条件执行不同的代码块,实现更复杂的逻辑功能。流程控制是程序设计的核心,它能让程序从简单的顺序执行转变为具有判断和选择能力的智能执行。
编程的魅力在于将复杂的问题分解为一系列可控的步骤,而运算符和表达式就是实现这些步骤的基础工具。随着学习的深入,你会发现这些基础知识如何共同构建出强大的程序。继续加油,下一篇我们将进入程序逻辑控制的世界!