一、内容概要
内容提neirong
关系运算符
逻辑运算符
逗号运算符
位运算
二、运算符
2.1 关系运算符
说明: >,<,>=,<=,==,!= (都是双目的)
- 所有关系运算符都是双目运算符(二元运算符),运算符左侧和右侧、可以是变量、常量(字面量(是指直接在代码中写出的 “值本身)、符号常量、使用const 修饰的变量)、还可以是表达式、举例:
a > b; // 变量
5 > 6; // 常量
a+b>c; // 表达式
- 关系运算符的结果是布尔类型、C语言中实际上没有布尔类型、我们用整型的 0 和 非 0 来表示成立(真)或者不成立(假)。
int a = 5, b = 4;
printf("%d,%d\n", a > b, a + b > 10);// 1,0 注意:计算机给我们返回的真-1,假-0
- C99标准引入 stdbool.h ,本质上是对0和1进行了封装。其实很简单,就是定义了两个符号常量:
#define true 1
#define false 0
浮点型比较需要用插值法:fabs(a - b)< 1e -6。使用fabs取绝对值函数、需要引入math,h
在C语言中,为什么浮点型不用 == 符号做等判断?请看下面例子:
#include <stdio.h>int main(int argc,char *argv[])
{float a = 1.1f + 1.2f; // a 预测结果:2.3ffloat b = 2.3f; // b 预测结果:2.3fprintf("1.1f + 1.2f = %.20f\n",a); // %.20f 意思是保留小数点后20位printf(" 2.3f = %.20f\n",b);double a1 = 1.1 * 2;printf("%d\n",a1 == 2.2);return 0;
}
操作 | 正确方式 | 错误方式 |
浮点数相等比较 | 使用误差范围(fabs(a - b) < epsilon)
| a==b |
浮点数大小比较 | 直接使用 > 或 < (误差不影响顺序) | - |
零比较 | fabs(a) < epsilon | a == 0.0 |
2.2 逻辑运算符
运算的结果为布尔值 、要么为 真-非0 ,要么为 假
(1)! :非(逻辑非)单目运算符,并且只能在操作数的左侧;非真即为假,非假即为真。(取反)
- 对一个数或者表达式取非奇数次,结果与原值相反(如: !(a % 2 != 0) )是1次取非,结果: a%2==0
- 对一个数或者表达式取非偶数次,结果与原值相同(如: !!(a % 2 == 0) )是2次取非,结果: a%2==0
(2)&& :与(逻辑与)双目运算符,当左右两侧的数据都为真时,最终的结果才为真(有假则为假)
- 当逻辑与运算时,左侧为假,右侧结果不会影响最终结果,右侧根本不会执行,最终的结果就是左侧的结果(假),这种现象称之为短路效果(短路与),这是C语言中提供的一种惰性计算,就是为了减少运算次数。
// 需求:要求成绩在0~100以内
int score = 90;
printf("%d\n", score >= 0 && score <= 100); // 1
注意:
- 避免链式调用(如: 0 <= score <= 100 ,应改为逻辑与: score >= 0 && score < = 100 )
- 在C语言中,上面的链式写法并不会编译报错,为什么不能用链式调用?请看下面例 子:
int score1 = 45, score2 = -65, score3 = 110;
// 预测:0 <= 45 <= 100 结果为1
printf("%d\n",0 <= score1 <= 100);//实际结果:0 <= score1 返回1,1
<= 100返回1,最终结果1,成立
// 预测:0 <= -65 <= 100 结果为0
printf("%d\n",0 <= score2 <= 100);//实际结果:0 <= score2 返回0,0
<= 100返回1,最终结果1,不成立
// 预测:0 <= 110 <= 100 结果为0
printf("%d\n",0 <= score3 <= 100);//实际结果:0 <= score3 返回1,1
<= 100返回1,最终结果1,不成立
经过以上测试,我们发现链式比较语法上没问题,可以通过编译,但是逻辑上有问题,所以不能用作条件判断。
(3)|| :或(逻辑或)双目运算符,当左右测数据都为假时,最终的结果才为假(有真则为真)
- 当逻辑或运算时,左侧为真,右侧结果不会影响最终结果,右侧根本不会执行,最终的结果就是左侧的结果(真),这种现象称之为短路效果(短路或),这是C语言中提供的一种惰性计算,就是为了减少运算次数。
// 需求:闰年计算公式
int year = 2025;
printf("%d\n", ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0));
2.3 逗号运算符
作用: 将若干个表达式 “串联起来” 如:a = 4,a +=3;
别称:顺序求值运算符
2.3.1 逗号表达式
语
表达式 1,表达式 2,... 表达式n;
求解过程:按从左到右的顺序分别计算各个表达式的值,其中最后一个表达式 n 的值就是整个逗号表达式的值。
案例:
#include <stdio.h>
int main()
{int a = 0, b = 0; // 这不是逗号表达式,这里称作逗号分隔符。// 逗号表达式int result = (a = 3, b = 5, a + b);// 8 整体是赋值表达式,=右侧是逗号表达式// 怎么判断一个表达式是逗号表达式还是赋值表达式,要看它最终的运算是赋值操作还是逗号操作// 结合条件判断int x = 10, y = 20;int max = (x++, y++, (x > y) ? x : y);// x=10, y=20, max = 21printf("result=%d, max=%d\n", result, max);// result=8, max=21return 0;
}
2.4 位运算
说明: 按位(bit)来进行运算操作的运算符,更多时候用于定制化应用开发和嵌入式开发。
语法: ~、&、|、<<、>>
~:按位取反
说明:单目运算符,数据的每一个bit位按位取反,也就是二进制数据位上,0变1,1变0 演示:

举例:
printf("%d\n",~5);
&:按位与
说明:双目运算符,对于运算符左右的两个数,对应的二进制位数据都为1时,结果为1、否则为0
演示:

举例:

printf("%d\n", 5 & 6); // 4
|: 按位或
说明:双目运算符,对于运算符左右的两个数据,对应的二进制位数据有一个为1,结果为1,否则为0
演示:

举例:
printf("%d\n",5 | 6);// 7
^:按位异或
说明:双目运算符,对于运算符左右的两个数据,对应二进制位数据相同,结果为0,不同为1
演示:

举例:
printf("%d\n",5 ^ 6);// 3