> 一篇搞定C语言所有运算符:算术、关系、逻辑、位、赋值、三目、sizeof
、优先级表全收录,附短路代码实验,写表达式不再懵!
一、算术运算符(整型&浮点通用)
运算符 |
功能 |
示例 |
备注 |
+ |
加/单目正 |
a + b 、+a |
单目很少写 |
- |
减/单目负 |
a - b 、-a |
常用 -a 取相反数 |
* |
乘 |
a * b |
双目 |
/ |
除 |
a / b |
整数相除舍去小数 |
% |
取模 |
a % b |
两操作数必须整型 |
++ |
自增 |
a++ 、 ++a |
前缀先加再用,后缀先用再加 |
-- |
自减 |
a-- 、 --a |
同上 |
注意:
- 减号也是负号,比如
-a
是取变量 a
的相反数
- 取模运算要求左右两边操作数必须是整型数据
- 自加和自减运算不仅可以对整型操作,也可以对浮点数、指针操作
- 前缀自加自减运算:先进行自加自减,再参与表达式运算
- 后缀自加自减运算:先参与表达式运算,再进行自加自减
① 整数除法陷阱
int a = 5, b = 2;
printf("%d\n", a / b); // 输出 2,不是 2.5
② 自增实验
int a = 100;
int b = 200;
int c = ++a; // a先自加1,变成101;然后再赋值给c,因此c等于101
int d = b++; // b先赋值给d,因此d等于200;然后b自加1,变成201float f = 3.14;
f++; // 浮点数也可以自增,f变成4.14int arr[5] = {1,2,3,4,5};
int *p = arr;
p++; // 指针自增,指向下一个元素
二、关系运算符(结果 0 或 1)
运算符 |
功能 |
示例 |
数学含义 |
> |
大于 |
a > b |
⩾ 不成立 |
>= |
大于等于 |
a >= b |
⩾ 成立 |
< |
小于 |
a < b |
< 成立 |
<= |
小于等于 |
a <= b |
≤ 成立 |
== |
相等 |
a == b |
≠ 请用 != |
!= |
不相等 |
a != b |
≠ |
关系表达式值:真=1,假=0
注意:
- 关系运算符用于判断运算符两边的表达式是否满足给定的大小条件。
- 由关系运算符组成的表达式称为关系表达式,其值为布尔型(非零则真)。
- 判断是否相等是双等号==,而不是一个等号(赋值)。
三、逻辑运算符(短路特性)
运算符 |
功能 |
示例 |
短路规则 |
! |
逻辑非 |
!a |
单目,真假翻转 |
&& |
逻辑与 |
a && b |
左假右不算 |
|| |
逻辑或 |
a || b |
左真右不算 |
int a = 0, b = 1;
int x = (a && ++b); // b 不会自增,因为左边已假
printf("b = %d\n", b); // 输出 1
四、位运算符(直接操作二进制)
运算符 |
名称 |
举例 |
功能说明 |
~ |
位逻辑反(单目运算符) |
~a |
将变量 a 中的每一位取反 |
& |
位逻辑与(双目运算符) |
a & b |
将变量 a 和 b 逐位进行与操作 |
| |
位逻辑或(双目运算符) |
a | b |
将变量 a 和 b 逐位进行或操作 |
^ |
位逻辑异或(双目运算符) |
a ^ b |
将变量 a 和 b 逐位进行异或操作 |
<< |
左移 |
a << 4 |
将变量 a 中的每一位向左移动4位 |
>> |
右移 |
a >> 4 |
将变量 a 中的每一位向右移动4位 |
重要说明
- 位运算符操作的对象是数据中的每一位(
int
需要操作32个二进制位,short
需要操作16个二进制位...)
- 运算规则:
- 位逻辑反、位逻辑与(有0得0)、位逻辑或(有1得1)拥有与逻辑运算相似的规则和一样的真值表
- 异或运算:相同为0,不同为1
- 移位运算:移出去的不要,空出来补(左移则补0,右移则补符号位)
示例代码
① 快速置位/清位
#include <stdio.h>
#include <stdint.h>int main(void)
{uint8_t a = 0b10101010; // 170uint8_t b = 0b11001100; // 204printf("a & b = 0x%02X\n", a & b); // 0x88 (0b10001000)printf("a | b = 0x%02X\n", a | b); // 0xEE (0b11101110)printf("a ^ b = 0x%02X\n", a ^ b); // 0x66 (0b01100110)printf("~a = 0x%02X\n", ~a); // 0x55 (0b01010101)printf("a << 2 = 0x%02X\n", a << 2); // 0xA8 (0b10101000)printf("a >> 2 = 0x%02X\n", a >> 2); // 0x2A (0b00101010)return 0;
}
② 交换两变量(无临时)
a ^= b;
b ^= a;
a ^= b;
五、赋值 & 复合赋值
赋值运算符
重要规则
- 不能对常量赋值,只能对变量赋值
- 不能对数组赋值(因为数组名字表示的是一个数据的地址)
- 可以连续赋值,顺序从右到左
// 正确示例
int a, b, c;
a = b = c = 10; // 连续赋值,等价于 c=10; b=c; a=b;// 错误示例
5 = a; // ❌ 不能对常量赋值
int arr[5];
arr = {1,2,3}; // ❌ 不能对数组名赋值
复合赋值符说明
- 当赋值符号左右两边有相同的操作数时,采用复合赋值符不仅直观,且能提高运算效率
- 除了以下10个复合运算符之外,生造别的复合运算符是非法的
简单形式 |
复合形式 |
等价写法 |
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 ^= b |
—— |
a = a << n |
a <<= n |
—— |
a = a >> n |
a >>= n |
—— |
六、三目运算符(唯一三元)
- 唯一需要三个操作数的运算符
- 语法:表达式1 ? 表达式2 : 表达式3
- 释义:当表达式1为真时,取表达式2,否则取表达式3
int m = (a > b) ? a : b; // 取较大值
//等价于
int m;
if (a > b) m = a;
else m = b;
七、sizeof 与 return
sizeof 运算符
- 含义:计算指定数据类型或者变量所占据内存的字节数(多大)
- 语法:sizeof(类型) 、sizeof(变量名) ,计算变量的字节数时圆括号可以省略(一般会保留)
举例
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(long double));int a[5];
printf("%d\n", sizeof(a));
printf("%d\n", sizeof a );
return运算符
- 含义:退出某个函数(如果退出的是主函数main,那么整个程序也就退出了)
- 语法:必须出现在函数体内,可以带函数对应类型的数据
举例
int main()
{return 0;//说明:return 用于函数返回;main 函数返回 0 表示成功。
}char func()
{return 'H';
}
八、运算符优先级 & 结合性(速查表)
优先级 |
运算符 |
结合方向 |
记忆口诀 |
1 |
() [] -> . |
左→右 |
括号下标成员 |
2 |
! ~ ++ -- + - * & sizeof |
右→左 |
单目 |
3 |
* / % |
左→右 |
乘除模 |
4 |
+ - |
左→右 |
加减 |
5 |
<< >> |
左→右 |
移位 |
6 |
< <= > >= |
左→右 |
关系 |
7 |
== != |
左→右 |
相等 |
8 |
& |
左→右 |
按位与 |
9 |
^ |
左→右 |
按位异或 |
10 |
| |
左→右 |
按位或 |
11 |
&& |
左→右 |
逻辑与 |
12 |
|| |
左→右 |
逻辑或 |
13 |
?: |
右→左 |
三目 |
14 |
= += -= 等 |
右→左 |
赋值 |
15 |
, |
左→右 |
逗号 |
实操建议:不确定就加括号,比背表更靠谱!
综合示例
int x = 5, y = 4, z;
z = x + y * 2 >> 1 & 3; // 等价于:z = ((x + (y * 2)) >> 1) & 3;
printf("%d\n", z); // 输出 1