运算符(operator)就是用来对变量、常量、表达式做运算的特殊符号。计算机常见的动作,加、减、比较、判断、按位运算,都靠它们。C语言 按功能可以把运算符分成六类,接下来看这六类各管什么。
一、算术运算符
负责数学计算:加 +、减 -、乘 *、除 /、取余 %,以及一目(unary)的正负号 +x -x 和自增自减 ++ --。看一段完整例子:
#include <stdio.h>
int main(void) {
int a = 25, b = 5;
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 = %d\n", +a);
printf("-a = %d\n", -a);
printf("a++ = %d\n", a++); // 先用旧值 25,再用完后 a 变 26
printf("a-- = %d\n", a--); // 先用旧值 26,再用完后 a 变 25
return 0;
}下面这段代码运行结果会依次得到:30、20、125、5、0、25、-25、25、26。有两处细节一定要留意。
- 整数除以整数,结果是整数。25 和 5 都是 int,25/5 = 5;但 7/2 会得到 3(小数就扔掉了)。想留小数,至少一边必须是浮点:
7.0 / 2才是 3.5。 a++和++a时机不一样。a++先把旧值交给表达式再用后自增;++a先自增再把新值交出来。单独一行写a++;时两者没区别。
二、关系运算符
比较两个值的大小关系,结果要么真要么假。C 语言里真 = 1,假 = 0:
#include <stdio.h>
int main(void) {
int a = 25, b = 5;
printf("a < b : %d\n", a < b); // 0
printf("a > b : %d\n", a > b); // 1
printf("a <= b : %d\n", a <= b); // 0
printf("a >= b : %d\n", a >= b); // 1
printf("a == b : %d\n", a == b); // 0 判断相等是两个等号
printf("a != b : %d\n", a != b); // 1 判断不相等
return 0;
}这里的 == 和 = 是两个不同的运算符:= 是赋值,== 才是比较。下面条件专题还会专门叮嘱一次。
三、逻辑运算符
把多个条件组合起来,或对条件取反。一共三个:
| 符号 | 含义 | 说明 |
|---|---|---|
&& | 逻辑与 | 两边都为真,结果才为真 |
|| | 逻辑或 | 任一边为真,结果就为真 |
! | 逻辑非 | 真变假、假变真 |
if (a > 0 && b > 0) { /* 两个都为正才进来 */ }
if (a > 0 || b > 0) { /* 至少一个为正就进来 */ }
if (!age) { /* age 为 0 时成立,等价于 age == 0 */ }注意"非 0 即真":C 语言里任何非 0 的整数都是真,只有 0 是假。
四、位运算符
直接对整数的二进制位下手,低级编程、性能敏感的场合常用:
| 符号 | 含义 | 说明 |
|---|---|---|
& | 按位与 | 同位都为 1 才为 1 |
| | 按位或 | 同位有一个为 1 即为 1 |
^ | 按位异或 | 同位不同才为 1 |
~ | 按位取反 | 把所有位翻转 |
<< | 左移 | 每位左移,右侧补 0,等于乘以 2 |
>> | 右移 | 每位右移,相当于除以 2 |
入门阶段只要知道它们存在,等学到状态位、掩码(Bitmask)等内容时再回来深入研究即可。
五、赋值运算符
最简单的 = 把右侧赋给左侧。为了省事,C 语言把"计算 + 赋值"合成了一批复合赋值:
int a = 10;
a += 5; // 等价于 a = a + 5;a 现在是 15
a -= 3; // 等价于 a = a - 3;a 现在是 12
a *= 2; // 等价于 a = a * 2;a 现在是 24
a /= 4; // 等价于 a = a / 4;a 现在是 6
a %= 4; // 等价于 a = a % 4;a 现在是 2位运算同样有复合写法:&=、|=、^=、>>=、<<=。性质都一样,先算,再写回去。
六、其他运算符
还有一些运算符,不好归入前面介绍的几大类。
sizeof(一目运算符),编译时就给出运算对象的字节数。sizeof(int)在 64 位桌上一般是 4。sizeof(arr)/sizeof(arr[0])是求数组元素个数的经典写法,数组篇会用到。- 三目(条件)运算符
? :,C 语言里唯一的三目运算符,可以当 if/else 的简写:大者 = (a > b) ? a : b;条件为真取第二段,为假取第三段。 - 取地址
&与解引用*,&x拿到 x 的地址,*p取指针 p 指向的值。scanf 里&age就是取地址,指针篇会展开讲。 - 强制类型转换
(类型),比如(double)7 / 2,先把 7 转成 double 再做除法,得到 3.5。
优先级怎么记
记住运算优先级规律:先乘除、后加减;算术运算优先于比较运算,比较运算又早于逻辑运算,赋值运算最后执行。拿捏不准优先级,直接加上括号,多多使用括号不会有问题。a + b > c && d == e 的真实执行流程:先计算 a+b,接着分别完成两次比较,最后再执行 && 逻辑判断。