1.5 运算符与表达式 | Operators and Expressions

发布于 2025-09-14  525 次阅读


运算符与表达式 | Operators and Expressions

一、回顾与引入

在前面的章节中,我们已经学会了:

  • 声明变量并给变量赋值
  • 使用printf()输出变量的值
  • 使用scanf()获取用户输入

在上一章的练习中,我们计算了圆的面积和周长:

float circumference = 2 * pi * radius;  // 使用了乘法运算符 *
float area = pi * radius * radius;      // 使用了乘法运算符 *

我们还在BMI计算中使用了除法:

float height_in_meters = height / 100.0;  // 使用了除法运算符 /

在上面两个例子中,我们频繁使用了如+、-、*、/等等各种简单运算符,今天我们要专门系统学习C语言中的各种运算符,让程序能够进行更复杂的数学计算和逻辑判断。

二、什么是运算符和表达式?

运算符(Operator)

运算符是用来对数据进行操作的符号,比如:

  • + 表示加法
  • - 表示减法
  • * 表示乘法
  • / 表示除法

表达式(Expression)

表达式是由操作数(变量、常量)和运算符组成的式子,比如:

3 + 5        // 简单表达式
a * b + c    // 复合表达式
a >= b       // 逻辑判断表达式 *本章会讲

表达式的值

每个表达式都有一个值,例如对于3 + 5这个表达式,它的值为8。这个值可以:

  • 直接使用:printf("%d", 3 + 5); // 输出8
  • 赋值给变量:int result = 3 + 5;
  • 作为其他表达式的一部分:int x = (3 + 5) * 2;

三、算术运算符

算术运算符用于进行数学计算,这是我们最常用的运算符。

基本算术运算符

运算符 名称 示例 结果
+ 加法 5 + 3 8
- 减法 5 - 3 2
* 乘法 5 * 3 15
/ 除法 10 / 3 3(整数除法)
/ 除法 10.0 / 3.0 3.33333(小数除法)
% 取模(求余) 10 % 3 1

必要地,这里对除法和取模运算做出说明:

除法

在C语言中,除法分为整除除法和小数除法。我们通过下面两个例子来简单认识:

//Division_Types.c
#include <stdio.h>
int main() {
    int a = 10, b = 3;
    printf("10 / 3 = ", a / b);  // 结果:3
}
//Division_Types.c
#include <stdio.h>
int main() {
    float a = 10.0, b = 3.0;
    printf("10.0 / 3.0 = ", a / b);  // 结果:3.33333
}

我们会发现,同样是除法运算符/,作整除除法还是小数除法取决于除数和被除数的数据类型。它们遵循以下关键规则

  • 两个整数相除 → 结果是整数(舍去小数部分)
  • 只要有一个浮点数参与 → 结果是浮点数

这也就解释了为什么10 / 3结果是310.0 / 3.0结果是3.33333
这是因为在直接使用103.0等数字参与表达式计算,而不像上面的例子中使用一个具有明确数据类型的变量时,103等不带小数点的数算作整型int,而10.03.0等带小数点的数算作浮点型float

还要值得一提的是,在赋值语句中,作整除除法还是小数除法与被赋值变量的数据类型无关。什么意思?

float result = 10 / 3;

即使这里result变量是浮点型,但10 / 3本身得到整数3。在赋值后,result确实是一个小数,但最终的值是3.0

取模

取模(mod)又叫求余,是带余除法的一部分。取模是针对两个整数的计算。它得到的是除法的余数。例如,因为10 ÷ 3 = 3 余 1
所以10 % 3的值是1

示例程序:基本算术运算

//Basic_Arithmetic.c
#include <stdio.h>

int main() {
    int a = 10, b = 3;

    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); // 取模运算
    // 还记得为什么输出%时,要写作%%么?答案在第1.3节的特殊字符与转义字符那一栏

    return 0;
}

运行结果:

a = 10, b = 3
a + b = 13
a - b = 7
a * b = 30
a / b = 3
a % b = 1

四、赋值运算符

基本赋值运算符 =

我们已经很熟悉基本的赋值运算符了:

int x = 10;    // 将10赋值给x

在程序设计时,我们可能会遇到下面的情况,例如我们有一个变量x

int x = 100;

假设我们想把变量x存储的值变为原来的两倍,并且仍然存储在变量x里。我们可以这样写:

x = x * 2;

这个操作不难理解,叫做乘法赋值。特点是程序会先取出 x 的值,乘上 2,再把结果存回 x。
此外,类似还有加法赋值、减法赋值、除法赋值、取模赋值等等。
例如:

x = x + 1; // x 由 100 变为 101
x = x - 3; // x 由 100 变为 97
x = x / 5; // x 由 100 变为 20
x = x % 3; // x 由 100 变为 1

复合赋值运算符

为了简化常见的自操作,C语言提供了复合赋值运算符:

运算符 等价写法 示例 含义
x += y x = x + y x += 5 x自增5
x -= y x = x - y x -= 3 x自减3
x *= y x = x * y x *= 2 x乘以2
x /= y x = x / y x /= 4 x除以4
x %= y x = x % y x %= 3 x对3取模

示例程序:复合赋值运算符

//Compound_Assignment.c
#include <stdio.h>

int main() {
    int score = 100;

    printf("初始分数: %d\n", score);

    score += 10;   // score = score + 10
    printf("加分后: %d\n", score);

    score -= 5;    // score = score - 5
    printf("扣分后: %d\n", score);

    score *= 2;    // score = score * 2
    printf("翻倍后: %d\n", score);

    score /= 3;    // score = score / 3
    printf("除以3后: %d\n", score);

    score %= 10;   // score = score % 10
    printf("对10取模后: %d\n", score);

    return 0;
}

运行结果:

初始分数: 100
加分后: 110
扣分后: 105
翻倍后: 210
除以3后: 70
对10取模后: 0

五、自增自减运算符

在我们刚才的例子里,我们了解到加法赋值和减法赋值。而在实际运用中,x = x + 1x = x - 1很常见。

因此,C语言提供了自增(++)和自减(--)运算符。它们是非常特殊的运算符,用于将变量的值增加或减少1。

基本语法

自增(++)和自减(--)语法很简单。例如对于变量xx++;++x;即可完成自增;x--;--x;即可完成自减。

根据自增运算符++和自减运算符--在变量x的前后位置不同,又分为前缀自增/自减(如++x;)和后缀自增/自减(如x--;)。

int x = 5;
x++;    // 后缀自增,x变成6
++x;    // 前缀自增,x变成7
x--;    // 后缀自减,x变成6
--x;    // 前缀自减,x变成5

在单独使用自增自减,即像上面的例子中一样,++x;等自增语句独立成行的时候,前缀和后缀不存在区别,都表示例如x = x + 1;。但当自增自减属于某一语句的一部分时,它们有些微的区别:

前缀 vs 后缀的区别

//Increment_Decrement.c
#include <stdio.h>

int main() {
    int x = 5;
    int y = x++; // 后缀自增,此时先将变量x的值5赋值给变量y,再将变量x自增为6。
    // 此时 x = 6, y = 5

    int a = 5;
    int b = ++a; // 前缀自增,此时先将变量a自增为6,再将变量a的值6赋值给变量b。
    // 此时 a = 6, b = 6
    return 0;
}

六、比较运算符

我们在前文讲解表达式时,举例曾提到逻辑判断表达式:

a >= b // 逻辑判断表达式 *本章会讲

我们在前文也提到

每个表达式都有一个值

那么逻辑判断表达式的值应该是什么?名为“判断”,它不应该是像3100这样的数。事实上,逻辑判断表达式的值只能是1(代表真,有时也写作true)或0(代表假,有时也写作false),用来表示这个逻辑判断表达式的内容是对的还是错的。

例如,3 > 2的值是1(真),而-1 > 3的值是0(假)。

比较运算符用于比较两个值的大小关系,是组成逻辑判断表达式的常见运算符。

比较运算符表

运算符 名称 示例 含义
== 等于 a == b a等于b
!= 不等于 a != b a不等于b
> 大于 a > b a大于b
< 小于 a < b a小于b
>= 大于等于 a >= b a大于等于b
<= 小于等于 a <= b a小于等于b

示例程序:比较运算符

//Comparison_Operators.c
#include <stdio.h>

int main() {
    int a = 10;
    int b = 5;

    printf("\n=== 比较结果 ===\n");
    printf("10 == 5 结果: %d\n", a == b);
    printf("10 != 5 结果: %d\n", a != b);
    printf("10 > 5 结果: %d\n", a > b);
    printf("10 < 5 结果: %d\n", a < b);
    printf("10 >= 5 结果: %d\n", a >= b);
    printf("10 <= 5 结果: %d\n", a <= b);

    return 0;
}

运行示例:

=== 比较结果 ===
10 == 5 结果: 0
10 != 5 结果: 1
10 > 5 结果: 1
10 < 5 结果: 0
10 >= 5 结果: 1
10 <= 5 结果: 0

常见错误:赋值与比较

在C语言中,=是赋值运算符,用于赋值语句。例如x = 5;==是比较运算符,用于比较两个变量是否相等。例如3 == 2的值是0(假),'A' == 'A'的值为1(真)。

此外值得一提的是,即使是赋值表达式x = 5也有它对应的值。这个值也只能是1(真)或0(假),表示赋值是否成功。因此通常情况下,赋值表达式的值一般都为1。这会在下一节提到判断语句的时候再次提到。

七、逻辑运算符

除了比较运算符,我们通常在逻辑处理中还伴随复杂条件。例如:

今天温度在18~22度之间

假设今天的的温度由变量t存储,这个自然语言表述的逻辑判断表达式,相当于是指“既要”t >= 18.0,“又要”t <= 22.0

我们在日常生活里常常遇到“而且”、“或者”、“不是”等逻辑关联词。它们正对应着三大逻辑运算符:与&&、或||、非!

逻辑运算符用于组合多个条件,在编写复杂判断时非常有用。

逻辑运算符表

运算符 名称 示例 含义
&& 逻辑与 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

在上面的例子中,“今天温度在18~22度之间”相当于t >= 18.0 && t <= 22.0,即温度t在同时满足大于等于18.0摄氏度和小于等于22.0摄氏度这两个简单条件时,这个表达式的值才为1(真),否则为0(假)。

八、运算符的优先级和结合性

当表达式中有多个运算符时,需要了解它们的执行顺序。

优先级表(从高到低,初学阶段了解即可)

优先级 运算符 结合性
1 () 左到右
2 ! ++ -- 右到左
3 * / % 左到右
4 + - 左到右
5 < <= > >= 左到右
6 == != 左到右
7 && 左到右
8 || 左到右
9 = += -= *= /= %= 右到左

示例:优先级的重要性

//Precedence_Examples.c
#include <stdio.h>

int main() {
    int a = 2, b = 3, c = 4;

    printf("a = %d, b = %d, c = %d\n", a, b, c);

    // 乘法优先于加法
    printf("a + b * c = %d\n", a + b * c);      // 等价于 a + (b * c) = 2 + 12 = 14
    printf("(a + b) * c = %d\n", (a + b) * c);  // (2 + 3) * 4 = 20

    // 比较运算符优先于逻辑运算符
    printf("a < b && b < c = %d\n", a < b && b < c);  // (2 < 3) && (3 < 4) = 1 && 1 = 1

    // 赋值运算符优先级最低
    int result = a + b * c;  // 先计算 a + b * c,再赋值给result
    printf("result = %d\n", result);

    return 0;
}

使用括号明确意图

即使了解优先级,也建议使用括号来明确表达意图:

// 不推荐:依赖优先级规则
int result1 = a + b * c / d - e;

// 推荐:使用括号明确意图
int result2 = a + ((b * c) / d) - e;

九、动手练习

练习:温度转换器

编写程序实现摄氏度和华氏度之间的转换:

  • 摄氏度转华氏度:F = C × 9/5 + 32
  • 华氏度转摄氏度:C = (F - 32) × 5/9

下一章预告: 掌握了运算符后,我们将学习条件语句(if-else),让程序能够根据不同的条件执行不同的操作,实现真正的智能判断!


这里是 /* Huajidawang */ 的个人主页