运算符与表达式

Tutorial: 教程一 Category: C语言 Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
5. 运算符与表达式

运算符是 C 语言中用于执行各种操作的符号或关键字。运算符与操作数结合形成表达式,表达式可以计算出一个值。理解各种运算符及其优先级与结合性,是编写正确和高效 C 程序的基础。

5.1 算术运算符

算术运算符用于执行基本的数学计算,包括加、减、乘、除和取模(余数)等操作。

常见算术运算符
运算符描述示例解释
+加法a + b将两个操作数相加
-减法a - b从第一个操作数中减去第二个操作数
*乘法a * b将两个操作数相乘
/除法a / b将第一个操作数除以第二个操作数
%取模(余数)a % b计算第一个操作数除以第二个操作数的余数
示例与详细解释
#include <stdio.h>

int main() {
    int a = 15;
    int b = 4;
    int sum, difference, product, quotient, remainder;

    // 加法
    sum = a + b; // 15 + 4 = 19
    printf("a + b = %d\n", sum);

    // 减法
    difference = a - b; // 15 - 4 = 11
    printf("a - b = %d\n", difference);

    // 乘法
    product = a * b; // 15 * 4 = 60
    printf("a * b = %d\n", product);

    // 除法
    quotient = a / b; // 15 / 4 = 3 (整数除法,舍去小数部分)
    printf("a / b = %d\n", quotient);

    // 取模
    remainder = a % b; // 15 % 4 = 3
    printf("a %% b = %d\n", remainder);

    return 0;
}

输出

a + b = 19
a - b = 11
a * b = 60
a / b = 3
a % b = 3
注意事项
  1. 整数除法:当两个整数相除时,结果也是一个整数,任何小数部分都会被舍去。
  2. 取模运算:取模运算仅适用于整数类型,计算两个整数相除后的余数。
更多示例
#include <stdio.h>

int main() {
    float x = 5.5;
    float y = 2.2;
    float result;

    // 加法
    result = x + y; // 5.5 + 2.2 = 7.7
    printf("x + y = %.1f\n", result);

    // 减法
    result = x - y; // 5.5 - 2.2 = 3.3
    printf("x - y = %.1f\n", result);

    // 乘法
    result = x * y; // 5.5 * 2.2 = 12.1
    printf("x * y = %.1f\n", result);

    // 除法
    result = x / y; // 5.5 / 2.2 = 2.5
    printf("x / y = %.1f\n", result);

    return 0;
}

输出

x + y = 7.7
x - y = 3.3
x * y = 12.1
x / y = 2.5
5.2 关系运算符

关系运算符用于比较两个值,结果是一个布尔值(真或假)。这些运算符常用于条件判断和循环控制。

常见关系运算符
运算符描述示例解释
==等于a == b如果 a 等于 b,结果为真(1)
!=不等于a != b如果 a 不等于 b,结果为真(1)
>大于a > b如果 a 大于 b,结果为真(1)
<小于a < b如果 a 小于 b,结果为真(1)
>=大于等于a >= b如果 a 大于等于 b,结果为真(1)
<=小于等于a <= b如果 a 小于等于 b,结果为真(1)
示例与详细解释
#include <stdio.h>

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

    // 等于
    if (a == b) {
        printf("a 等于 b\n");
    } else {
        printf("a 不等于 b\n");
    }

    // 不等于
    if (a != b) {
        printf("a 不等于 b\n");
    }

    // 大于
    if (a > b) {
        printf("a 大于 b\n");
    } else {
        printf("a 不大于 b\n");
    }

    // 小于
    if (a < b) {
        printf("a 小于 b\n");
    }

    // 大于等于
    if (a >= 10) {
        printf("a 大于等于 10\n");
    }

    // 小于等于
    if (b <= 20) {
        printf("b 小于等于 20\n");
    }

    return 0;
}

输出

a 不等于 b
a 不大于 b
a 小于 b
a 大于等于 10
b 小于等于 20
更多示例
#include <stdio.h>

int main() {
    int x = 5;
    int y = 5;
    int z = 10;

    // 使用关系运算符进行比较
    printf("x == y: %d\n", x == y); // 1(真)
    printf("x != z: %d\n", x != z); // 1(真)
    printf("z > y: %d\n", z > y);   // 1(真)
    printf("x < z: %d\n", x < z);   // 1(真)
    printf("y >= x: %d\n", y >= x); // 1(真)
    printf("z <= 10: %d\n", z <= 10); // 1(真)

    return 0;
}

输出

x == y: 1
x != z: 1
z > y: 1
x < z: 1
y >= x: 1
z <= 10: 1
注意事项
  • 布尔值:C 语言中,真用1表示,假用0表示。
  • 类型兼容性:在比较时,操作数应尽量类型一致,避免隐式类型转换带来的问题。
5.3 逻辑运算符

逻辑运算符用于连接两个或多个条件表达式,产生一个布尔值结果。这些运算符在条件判断和控制结构中尤为重要。

常见逻辑运算符
运算符描述示例解释
&&逻辑与(AND)a && b如果 a 和 b 都为真,结果为真(1)
``逻辑或(OR)
!逻辑非(NOT)!a如果 a 为假,结果为真(1);如果 a 为真,结果为假(0)
示例与详细解释
#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int c = 30;

    // 逻辑与运算
    if (a < b && b < c) {
        printf("a < b 且 b < c\n");
    }

    // 逻辑或运算
    if (a > b || b < c) {
        printf("a > b 或 b < c\n");
    }

    // 逻辑非运算
    if (!(a > b)) {
        printf("!(a > b) 即 a <= b\n");
    }

    return 0;
}

输出

a < b 且 b < c
a > b 或 b < c
!(a > b) 即 a <= b
更多示例
#include <stdio.h>

int main() {
    int x = 5;
    int y = 10;

    // 逻辑与
    if (x > 0 && y > 0) {
        printf("x 和 y 都是正数\n");
    }

    // 逻辑或
    if (x < 0 || y > 0) {
        printf("x 是负数 或 y 是正数\n");
    }

    // 逻辑非
    if (!(x == y)) {
        printf("x 不等于 y\n");
    }

    return 0;
}

输出

x 和 y 都是正数
x 是负数 或 y 是正数
x 不等于 y
注意事项
  • 短路评估:逻辑与和逻辑或运算符具有短路特性。例如,a && b,如果 a 为假,b 将不再被计算。
  • 优先级:逻辑运算符的优先级低于关系运算符,高于赋值运算符。使用括号可以明确运算顺序。
5.4 位运算符

位运算符用于对整数类型的位(0 和 1)进行操作。这些运算符在底层编程、硬件控制和高效算法实现中非常有用。

常见位运算符
运算符描述示例解释
&按位与a & b对应位都为 1 时结果为 1,否则为 0
``按位或`a
^按位异或a ^ b对应位不同则为 1,相同则为 0
~按位取反~a对每一位取反,即 0 变 1,1 变 0
<<左移a << 2将位向左移动指定的位数
>>右移a >> 2将位向右移动指定的位数
示例与详细解释
#include <stdio.h>

int main() {
    unsigned char a = 5;    // 二进制:00000101
    unsigned char b = 9;    // 二进制:00001001
    unsigned char result;

    // 按位与
    result = a & b; // 00000101 & 00001001 = 00000001
    printf("a & b = %d\n", result); // 输出 1

    // 按位或
    result = a | b; // 00000101 | 00001001 = 00001101
    printf("a | b = %d\n", result); // 输出 13

    // 按位异或
    result = a ^ b; // 00000101 ^ 00001001 = 00001100
    printf("a ^ b = %d\n", result); // 输出 12

    // 按位取反
    result = ~a; // ~00000101 = 11111010
    printf("~a = %d\n", result); // 输出 250(对于unsigned char)

    // 左移
    result = a << 2; // 00000101 << 2 = 00010100
    printf("a << 2 = %d\n", result); // 输出 20

    // 右移
    result = b >> 2; // 00001001 >> 2 = 00000010
    printf("b >> 2 = %d\n", result); // 输出 2

    return 0;
}

输出

a & b = 1
a | b = 13
a ^ b = 12
~a = 250
a << 2 = 20
b >> 2 = 2
更多示例
#include <stdio.h>

int main() {
    unsigned int x = 12; // 二进制:00001100
    unsigned int y = 5;  // 二进制:00000101
    unsigned int z;

    // 按位与
    z = x & y; // 00001100 & 00000101 = 00000100 (4)
    printf("x & y = %u\n", z);

    // 按位或
    z = x | y; // 00001100 | 00000101 = 00001101 (13)
    printf("x | y = %u\n", z);

    // 按位异或
    z = x ^ y; // 00001100 ^ 00000101 = 00001001 (9)
    printf("x ^ y = %u\n", z);

    // 按位取反
    z = ~x; // ~00001100 = 11110011... (对于unsigned int, 结果依系统而定)
    printf("~x = %u\n", z);

    // 左移
    z = x << 1; // 00001100 << 1 = 00011000 (24)
    printf("x << 1 = %u\n", z);

    // 右移
    z = y >> 1; // 00000101 >> 1 = 00000010 (2)
    printf("y >> 1 = %u\n", z);

    return 0;
}

输出

x & y = 4
x | y = 13
x ^ y = 9
~x = 4294967283
x << 1 = 24
y >> 1 = 2
应用场景
  1. 位掩码:使用按位与操作提取特定位的数据。

    #include <stdio.h>
    
    int main() {
        unsigned char flags = 0b10101100; // 假设这是一个标志位
        unsigned char mask = 0b00001000;  // 掩码,提取第四位
    
        unsigned char result = flags & mask;
        if (result) {
            printf("第四位是1\n");
        } else {
            printf("第四位是0\n");
        }
    
        return 0;
    }
    

    输出

    第四位是1
    
  2. 设置、清除和切换位

    #include <stdio.h>
    
    int main() {
        unsigned char flags = 0b00000000; // 初始状态
    
        // 设置第三位
        flags |= 0b00000100; // 00000000 | 00000100 = 00000100
        printf("设置第三位后: %u\n", flags); // 输出 4
    
        // 清除第三位
        flags &= ~0b00000100; // 00000100 & 11111011 = 00000000
        printf("清除第三位后: %u\n", flags); // 输出 0
    
        // 切换第二位
        flags ^= 0b00000010; // 00000000 ^ 00000010 = 00000010
        printf("切换第二位后: %u\n", flags); // 输出 2
    
        // 再次切换第二位
        flags ^= 0b00000010; // 00000010 ^ 00000010 = 00000000
        printf("再次切换第二位后: %u\n", flags); // 输出 0
    
        return 0;
    }
    

    输出

    设置第三位后: 4
    清除第三位后: 0
    切换第二位后: 2
    再次切换第二位后: 0
    
注意事项
  • 优先级:位运算符的优先级低于算术运算符,高于赋值运算符。使用括号可以明确运算顺序。
  • 类型:位运算符仅适用于整数类型(intcharlong等)。
5.5 赋值运算符

赋值运算符用于将右侧的值赋给左侧的变量。C 语言提供了多种赋值运算符,以简化变量的赋值操作。

常见赋值运算符
运算符描述示例解释
=简单赋值a = b将 b 的值赋给 a
+=加后赋值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
<<=左移后赋值a <<= 2等价于 a = a << 2
>>=右移后赋值a >>= 2等价于 a = a >> 2
&=按位与后赋值a &= b等价于 a = a & b
`=`按位或后赋值`a
^=按位异或后赋值a ^= b等价于 a = a ^ b
示例与详细解释
#include <stdio.h>

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

    // 简单赋值
    printf("初始值: a = %d, b = %d\n", a, b);

    // 加后赋值
    a += b; // a = a + b => 10 + 5 = 15
    printf("a += b 后: a = %d\n", a);

    // 减后赋值
    a -= b; // a = a - b => 15 - 5 = 10
    printf("a -= b 后: a = %d\n", a);

    // 乘后赋值
    a *= b; // a = a * b => 10 * 5 = 50
    printf("a *= b 后: a = %d\n", a);

    // 除后赋值
    a /= b; // a = a / b => 50 / 5 = 10
    printf("a /= b 后: a = %d\n", a);

    // 取模后赋值
    a %= 3; // a = a % 3 => 10 % 3 = 1
    printf("a %%= 3 后: a = %d\n", a);

    // 左移后赋值
    a <<= 2; // a = a << 2 => 1 << 2 = 4
    printf("a <<= 2 后: a = %d\n", a);

    // 右移后赋值
    a >>= 1; // a = a >> 1 => 4 >> 1 = 2
    printf("a >>= 1 后: a = %d\n", a);

    // 按位与后赋值
    a &= b; // a = a & b => 2 & 5 = 0
    printf("a &= b 后: a = %d\n", a);

    // 按位或后赋值
    a |= b; // a = a | b => 0 | 5 = 5
    printf("a |= b 后: a = %d\n", a);

    // 按位异或后赋值
    a ^= b; // a = a ^ b => 5 ^ 5 = 0
    printf("a ^= b 后: a = %d\n", a);

    return 0;
}

输出

初始值: a = 10, b = 5
a += b 后: a = 15
a -= b 后: a = 10
a *= b 后: a = 50
a /= b 后: a = 10
a %= 3 后: a = 1
a <<= 2 后: a = 4
a >>= 1 后: a = 2
a &= b 后: a = 0
a |= b 后: a = 5
a ^= b 后: a = 0
注意事项
  • 操作顺序:赋值运算符具有从右到左的结合性。
  • 优先级:赋值运算符的优先级较低,通常与括号结合使用以确保正确的运算顺序。
5.6 条件运算符

条件运算符(又称三元运算符)是一种简洁的条件判断方法,语法形式为条件 ? 表达式1 : 表达式2。根据条件的真假,选择执行表达式 1 或表达式 2。

条件运算符的语法
条件 ? 表达式1 : 表达式2
  • 条件:一个布尔表达式,如果为真(非零),则执行表达式 1;否则执行表达式 2。
  • 表达式 1表达式 2:可以是任何类型的表达式。
示例与详细解释
#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int max;

    // 使用条件运算符找出较大值
    max = (a > b) ? a : b; // 如果a > b为真,则max = a;否则max = b
    printf("较大的数是: %d\n", max);

    // 另一个示例
    int num = 15;
    char *result;

    // 判断num是否为偶数
    result = (num % 2 == 0) ? "偶数" : "奇数";
    printf("num 是 %s\n", result);

    return 0;
}

输出

较大的数是: 20
num 是 奇数
更多示例
#include <stdio.h>

int main() {
    int x = 5;
    int y = 10;
    int z;

    // 条件运算符嵌套
    z = (x > y) ? x : (y > 0 ? y : -1);
    printf("z = %d\n", z); // 输出 10

    // 使用条件运算符简化赋值
    int age = 18;
    char *status;

    status = (age >= 18) ? "成年人" : "未成年人";
    printf("年龄 %d 是 %s\n", age, status);

    // 结合算术运算符使用
    int a = 7;
    int b = 3;
    int result;

    result = (a > b) ? (a - b) : (b - a);
    printf("差值: %d\n", result); // 输出 4

    return 0;
}

输出

z = 10
年龄 18 是 成年人
差值: 4
注意事项
  • 可读性:虽然条件运算符可以简化代码,但过度使用或嵌套使用可能会降低代码的可读性。应在保持简洁的同时,确保代码清晰易懂。
  • 类型一致性:条件运算符的两个表达式(表达式 1 和表达式 2)应尽量类型一致,以避免不必要的类型转换。
5.7 运算符优先级与结合性

在 C 语言中,运算符优先级决定了表达式中不同运算符的计算顺序,而结合性决定了当具有相同优先级的运算符出现在表达式中时,运算的方向。

运算符优先级

不同运算符具有不同的优先级。优先级高的运算符会先被计算。以下是常见运算符的优先级列表(从高到低)。

优先级运算符描述
1() [] -> .函数调用、数组下标、成员访问
2! ~ ++ -- - + * &单目运算符
3* / %乘法、除法、取模
4+ -加法、减法
5<< >>左移、右移
6< <= > >=关系运算符
7== !=相等运算符
8&按位与
9^按位异或
10``
11&&逻辑与
12`
13?:条件运算符(三元运算符)
14= += -= *= /= %= <<= >>= &= ^= `=`
15,逗号运算符
运算符结合性

结合性决定了当表达式中存在多个相同优先级的运算符时,运算的顺序。

结合性运算符
从左到右() [] -> .、算术运算符、关系运算符、逻辑运算符等
从右到左赋值运算符、条件运算符(三元运算符)等
示例与详细解释
示例 1:优先级高的运算符先计算
#include <stdio.h>

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

    // 运算符优先级示例
    c = a + b * 2; // 先计算 b * 2,再加 a
    printf("a + b * 2 = %d\n", c); // 输出 25

    c = (a + b) * 2; // 使用括号改变优先级,先计算 a + b,再乘以2
    printf("(a + b) * 2 = %d\n", c); // 输出 30

    return 0;
}

输出

a + b * 2 = 25
(a + b) * 2 = 30
示例 2:结合性示例
#include <stdio.h>

int main() {
    int x = 1;
    int y = 2;
    int z = 3;
    int a, b;

    // 从左到右结合性
    a = x = y + z; // y + z = 5, x = 5, a = 5
    printf("a = %d, x = %d\n", a, x); // 输出 a = 5, x = 5

    // 赋值运算符的右到左结合性
    b = a = x = 10; // x = 10, a = 10, b = 10
    printf("a = %d, b = %d, x = %d\n", a, b, x); // 输出 a = 10, b = 10, x = 10

    return 0;
}

输出

a = 5, x = 5
a = 10, b = 10, x = 10
示例 3:条件运算符的优先级与结合性
#include <stdio.h>

int main() {
    int a = 5, b = 10, c = 15;
    int result;

    // 条件运算符的优先级较低,需要使用括号确保运算顺序
    result = a > b ? a : b > c ? b : c;
    // 等价于: result = (a > b) ? a : (b > c ? b : c)
    printf("Result: %d\n", result); // 输出 15

    return 0;
}

输出

Result: 15
运算符优先级表

以下是 C 语言中常见运算符的优先级和结合性列表,便于查阅和参考。

优先级运算符描述结合性
1() [] -> .函数调用、数组下标、成员访问从左到右
2! ~ ++ -- - + * &单目运算符从右到左
3* / %乘法、除法、取模从左到右
4+ -加法、减法从左到右
5<< >>左移、右移从左到右
6< <= > >=关系运算符从左到右
7== !=相等运算符从左到右
8&按位与从左到右
9^按位异或从左到右
10``按位或
11&&逻辑与从左到右
12``
13?:条件运算符(三元运算符)从右到左
14= += -= *= /= %= <<= >>= &= ^= `=`赋值运算符
15,逗号运算符从左到右
5.8 总结

运算符与表达式是 C 语言编程中的核心概念。通过理解不同运算符的功能、优先级和结合性,能够编写出逻辑正确且高效的代码。以下是本节的关键点:

  1. 算术运算符:用于基本的数学计算,如加、减、乘、除和取模。
  2. 关系运算符:用于比较两个值,返回布尔值(真或假)。
  3. 逻辑运算符:用于连接多个条件表达式,产生布尔值结果。
  4. 位运算符:用于对整数类型的位进行操作,适用于底层编程和高效算法。
  5. 赋值运算符:用于将值赋给变量,提供多种简化赋值的方式。
  6. 条件运算符:一种简洁的条件判断方法,通常用于简化if-else语句。
  7. 运算符优先级与结合性:决定表达式中运算的顺序和方向,确保代码按预期执行。