运算符是用于执行各种操作的符号,如加法、比较、逻辑判断等;表达式是由运算符和操作数组成的式子,每个表达式都有一个确定的值。 掌握C语言的运算符及其优先级、结合性,是编写正确程序的基础。本章将系统介绍C语言中所有运算符及其用法。
C语言提供丰富的运算符,根据功能可分为以下几类:
算术运算符用于执行基本的数学运算。
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
+ | 加法 | a + b | 求两个数之和 |
- | 减法 | a - b | 求两个数之差 |
* | 乘法 | a * b | 求两个数之积 |
/ | 除法 | a / b | 两个数相除。如果操作数都是整数,结果为整数(截断) |
% | 取模(求余) | a % b | 求整除后的余数,操作数必须为整数 |
++ | 自增 | a++ 或 ++a | 变量增加1 |
-- | 自减 | a-- 或 --a | 变量减少1 |
#include <stdio.h>
int main() {
int a = 10, b = 3;
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); // 整数除法,结果为3
printf("a %% b = %d\n", a % b); // 取余,结果为1
// 自增自减
int x = 5;
printf("x++ = %d\n", x++); // 先使用x(5),再自增
printf("现在 x = %d\n", x);
printf("++x = %d\n", ++x); // 先自增,再使用(x为7)
return 0;
}
++(a+b) 是错误的。
关系运算符用于比较两个值的大小关系,返回结果为1(真)或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 |
逻辑运算符用于组合多个条件,结果也为真(1)或假(0)。
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
&& | 逻辑与 | a && b | 两者都为真时结果为真 |
|| | 逻辑或 | a || b | 至少一个为真时结果为真 |
! | 逻辑非 | !a | 将真变假,假变真 |
#include <stdio.h>
int main() {
int a = 5, b = 3, c = 8;
printf("a > b && a < c: %d\n", (a > b) && (a < c)); // 1 (真)
printf("a > b || a > c: %d\n", (a > b) || (a > c)); // 1 (真)
printf("!(a > b): %d\n", !(a > b)); // 0 (假)
// 短路求值示例
int x = 0;
if (x && (++x > 0)) { // 因为x为0,左边为假,右边表达式不会执行
// 不会进入
}
printf("x = %d\n", x); // 输出0,证明++x未执行
return 0;
}
&& 和逻辑或 || 采用短路求值策略,即当左侧表达式已能确定最终结果时,右侧表达式不再计算。
位运算符直接对整数的二进制位进行操作,是C语言底层操作的重要特性。
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
& | 按位与 | a & b | 对应位都为1时结果为1 |
| | 按位或 | a | b | 对应位至少一个为1时结果为1 |
^ | 按位异或 | a ^ b | 对应位不同时结果为1 |
~ | 按位取反 | ~a | 将每一位取反 |
<< | 左移 | a << n | 将二进制位左移n位,低位补0 |
>> | 右移 | a >> n | 将二进制位右移n位,无符号数高位补0,有符号数依编译器而定 |
#include <stdio.h>
int main() {
unsigned char a = 0b10101100; // 172
unsigned char b = 0b01101101; // 109
printf("a & b = %u\n", a & b); // 00101100 = 44
printf("a | b = %u\n", a | b); // 11101101 = 237
printf("a ^ b = %u\n", a ^ b); // 11000001 = 193
printf("~a = %u\n", (unsigned char)~a); // 01010011 = 83
unsigned char c = 0b00001010; // 10
printf("c << 2 = %u\n", c << 2); // 00101000 = 40
printf("c >> 1 = %u\n", c >> 1); // 00000101 = 5
return 0;
}
赋值运算符用于将右侧表达式的值赋给左侧变量。除了基本赋值=,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 &= b | a = a & b |
|= | a |= b | a = a | b |
^= | a ^= b | a = a ^ b |
<<= | a <<= n | a = a << n |
>>= | a >>= n | a = a >> n |
格式:表达式1 ? 表达式2 : 表达式3
如果表达式1为真,则整个表达式的值为表达式2的值,否则为表达式3的值。
#include <stdio.h>
int main() {
int a = 10, b = 20;
int max = (a > b) ? a : b; // max = 20
printf("较大值为: %d\n", max);
// 可以嵌套使用
int x = 5, y = 8, z = 3;
int max3 = (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);
printf("三个数中的最大值: %d\n", max3);
return 0;
}
逗号运算符,用于将多个表达式组合成一个表达式,整个表达式的值为最后一个表达式的值。
#include <stdio.h>
int main() {
int a, b;
a = (b = 3, b + 2); // 先计算b=3,再计算b+2=5,然后将5赋给a
printf("a = %d, b = %d\n", a, b); // a=5, b=3
// 常用于循环中
for (int i = 0, j = 10; i < j; i++, j--) {
printf("i=%d, j=%d\n", i, j);
}
return 0;
}
sizeof是一个单目运算符,用于计算数据类型或变量所占内存的字节数,结果类型为size_t。
#include <stdio.h>
int main() {
int a;
printf("Size of int: %zu\n", sizeof(int));
printf("Size of a: %zu\n", sizeof a); // 括号可省略
printf("Size of double: %zu\n", sizeof(double));
printf("Size of array: %zu\n", sizeof(int[10])); // 计算类型长度
return 0;
}
当一个表达式中包含多个运算符时,优先级决定运算顺序,结合性决定相同优先级的运算符是从左向右还是从右向左计算。
| 优先级 | 运算符 | 结合性 |
|---|---|---|
| 1(最高) | () [] . -> | 从左到右 |
| 2 | ++ -- ! ~ + - * & (类型) sizeof(单目) | 从右到左 |
| 3 | * / % | 从左到右 |
| 4 | + - | 从左到右 |
| 5 | << >> | 从左到右 |
| 6 | < <= > >= | 从左到右 |
| 7 | == != | 从左到右 |
| 8 | & | 从左到右 |
| 9 | ^ | 从左到右 |
| 10 | | | 从左到右 |
| 11 | && | 从左到右 |
| 12 | || | 从左到右 |
| 13 | ?: | 从右到左 |
| 14 | = += -= *= /= %= &= ^= |= <<= >>= | 从右到左 |
| 15(最低) | , | 从左到右 |
()明确运算顺序,可以提高代码可读性,避免歧义。
在表达式中,不同类型的操作数会进行类型转换,以保证运算的合法性。
(类型)表达式强制转换,如(float)a / b。#include <stdio.h>
int main() {
int a = 10;
float b = 3.14;
double c = 2.718;
// 隐式转换:a 转换为 float 与 b 运算,结果转为 double 再与 c 运算
double result = a + b + c;
// 强制转换:避免整数除法
int x = 5, y = 2;
float ratio = (float)x / y; // 2.5 而不是 2
printf("ratio = %f\n", ratio);
return 0;
}
运算符与表达式是C语言的核心组成部分。熟练运用各类运算符并理解优先级、结合性,能让你写出更简洁、高效的代码。 下一章将学习流程控制语句(if、switch、循环等),开始构建程序的逻辑结构。