运算符
赋值运算符
“="称之为赋值运算符,其作用是将一个数据赋值给一个变量,如:int a = 5 ;
执行赋值运算的结果,是将右边的数据存入左边变量对应的内存单元,赋值运算的顺序:自左向右
赋值规则
如果赋值运算符两侧的类型不一致,在赋值时进行类型转换,转换规则:
- 浮点型→类型变量:舍弃小数部分。如(
int a= 5.5 → a =5
) - 整型→浮点型变量:数值不变,以浮点型存储。如:(
double a = 5 → a = 5.000000...
) - 字符型→整型变量:放在整型的第8位,保持原值不变规则。(如
int a = 'A'
)
赋值表达式
实现赋值运算的表达式:
语法:
变量 = 表达式 ;
案例:
a = 5; //将一个int类型的常量(字面量)赋值给一个int类型变量,解释:字面量就是常量的一种
y = 2 * x + 3;//将一个表达式运算的结果赋值给变量
a = a + 1; //将一个表达式运算的结果复制给变量
作用:
将右边表达式的值赋值给左边的变量。赋值表达式的取值取自左边变量的值。
什么是表达式?
表达式=运算数+运算符
什么是运算数?
常量、变量、表达式都可以是运算数。
复合赋值运算符
+= 、-=、 *=、 /=、 %=...、&= 、|= 、>>=、 <<=、 ~= 、^=
int a = 1;
a += 3; //等价于 a = a + 3;
int c = 2;
c /=c; //等价于 c = c / c; c = 2 / 2; c = 1;
// ...其他复合运算符使用同理
注意:
①在运算时:不能将(=)写作(==)
②赋值运算符的优先级属于最低(除了逗号运算符以外)(a+b)/c,一般都是留到最后运算
关系运算符
>、<、>=、<=、==、!=、
-
所有的关系运算符都是双目运算符(二元运算符),运算符的左侧和右侧可以是变量、可以是常量(字面量、符号常量、使用const修饰的变量)、还可以是表达式。举例:
a > b,5 > 6, a+b > c
-
关系运算符运算结果的布尔类型,C语言中的布尔类型使用整型int来表示,使用
非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 ture 1
#define flase 0
注意:
-
避免链式使用(如:
0 <= score <= 100
),应该改为逻辑与:score >= 0 && score <= 100
int score1 = 45,score2 = -65,score3 = 110; printf("%d\n",0 <= score1 <= 100);//0 <= score1 → 1 <= 100 → 1 最终结果是真,45在 0~100之间,成立 printf("%d\n",0 <= score2 <= 100);//0 <= score2 → 1 <= 100 → 1 最终结果是真,-65在 0~100之间,成立? printf("%d\n",0 <= score3 <= 100);//0 <= score3 → 1 <= 100 → 1 最终结果是真,110在 0~100之间,成立?
经过以上测试,我们发现链式比较语法上没有问题,可以通过编译,但是逻辑上有问题,所以不能用作条件判断。
-
浮点数比较需要差值法:
fabs(a - b)<1e-6
0.000001。使用fabs 取绝对值函数,需要引入**math.h
**3.000 000可以认为和3.000 001相等
/************************************************************************* > File Name: demo01.c > Author: 小刘 > Description: > Created Time: 2025年05月06日 星期二 09时24分10秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { float a = 0.1f + 0.2f; float b = 0.3f; printf("0.1 +0.2 = %.20f\n",a);//%.20f 意思是小数点保留20位 printf(" 0.3 = %.20f\n",b); double a1 = 0.1 * 2; printf("%d\n",a1 == 0.2); return 0; }
总结:
操作 正确方式 错误方式 浮点数相等比较 使用误差范围(fabs(a - b) < epsilon) a == b 浮点数大小比较 直接使用 > 或 < (误差不影响顺序) - 零比较 fabs(a ) < epsilon a == 0.0
逻辑运算符
运算的结果为布尔值,要么为真(非0),要么为假(0)
-
!
:非(逻辑非)单目运算符,并且只能在操作数左侧;非真即为假、非假即为真。(取反)- 对于一个数或者表达式取非奇数次,结果与原值相反(奇变偶),!(a%2!=0)取偶次数
- 对于一个数或者表达式取非偶数次,结果与原值相反(偶变奇),!(a%2!=0)取奇次数
-
&&
:==与(逻辑与)==双目运算符,当左右两侧的数据都为真时,最终的结果才为真(有假则为假)当逻辑运算时,左侧为假,右侧结果不会影响最终结果,右侧不会执行,最终结果就是左侧的结果(假),这种现象称之为短路效果(短路与),这是C语言中提供的一种惰性计算,就是为了减少运算次数。
案例:
//需求:要求成绩在0~100以内 int score = 90; score >= 0 && score <= 100;//1
-
||
:==或(逻辑与或)==双目运算符,当左右两侧的数据都为假时,最终的结果才为假(有真则为真)当逻辑运算时,左侧为真,右侧结果不会影响最终结果,右侧不会执行,最终结果就是左侧的结果(真),这种现象称之为短路效果(短路或),这是C语言中提供的一种惰性计算,就是为了减少运算次数。
案例:
//需求:闰年计算公式 int year = 2025; (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
逗号运算符
**作用:**将若干个表达式“串联起来”,如:a = 4, a+=3;
**别称:**顺序求值运算符
逗号表达式
语法:
表达式1,表达式2,...表达式n,
**求解过程:**按从从左到右
案例:
#include<stdio.h>
int main()
{
int a = 0, b = 0;
//逗号表达式
int result = (a = 3,b = 5,a + b);//整体是赋值表达式
//怎么判断一个表达式是逗号还是赋值表达式,要是它最终的运算是赋值操作还是逗号操作
//结合条件判断
int x = 10, y = 20;
int max = (x++, y++,(x>y) ? x : y);//x = 11, y = 21, max = 21
printf("result=%d,max=%d\n",result,max);//result=8,max=21
return 0;
}
位运算
说明:按位(bit)来进行运算操作的运算符,更多时候用于嵌入式开发。
语法:~、&、|、^、<<、>>
~:按为取反
说明:单目运算符,数据每一个bit位按位取反,也就是二进制数据位上,0变成1,1变成0。
演示:
举例:
unsigned char ret = ~0x05;
printf("%d\n",~5);
&:按位与
说明:双目运算符,对于运算符左右的两个数,对应二进制位数据都为1时,结果为1,否则为0
演示:
举例:
printf("%d\n",5 & 6);//4
|:按位或
说明:双目运算符,对于运算符左右两个数,对应二进制位数据有一个1则为1,否则为0
演示:
举例:
printf("%d\n",5|6);//?
^:按位异或
说明:双目运算符,对于运算符左右的两个数,对应的二进制数据相同,结果为0,不同则为1
演示:
举例:
printf("%d\n",5 ^ 6);// 3
<<:左移,按位左移
说明:原操作数所有二进制位数想左移整体移动指定位。(高舍低补)
无符号左移;
- 语法:
操作数 << 移动位数
- 举例:
unsigned int a = 3 << 3;//24 将3左移3位,可以套用公式:3 * 2 ^ 3
unsigned int b = 5 << 4;//80 将5左移4位,可以套用公式:5 * 2 ^ 4
有符号左移:
-
语法:
操作数 << 移动位数
-
举例:
int a = -3 << 3;//-24 将-3左移3位,可以套用公式:-3 * 2 ^ 3
int b = 240 << 2;///960 将240左移2位,可以套用公式:240 * 2 ^ 2
- 注意:
- 如果移除的高位都是0,我们可以这样理解:a << n,可以看做是 a ∗ 2 n a*2^n a∗2n
- 如果移出的高位都是1,我们是不能使用上面的计算公式的。
>>:右移,按位右移
说明:原操作数所有二进制位数想右移整体移动指定位,移出的数据舍弃(高补低舍)。
如果操作数是无符号数;左边用0补齐
如果操作数是有符号数:左边用是,什么不全,取决于计算机系统
- 逻辑右移:用0补全
- 逻辑左移:用1补全
大部分情况下,系统遵循“算术右移”
无符号右移:
语法:
操作数 >> 移动位数
举例:
unsigned char a = 3 >> 3;//0
演示:
有符号右移:
语法:
操作数 >> 移动位数
演示:
char a = -3 >> 3;// -1
演示:
关于移位运算过程:
原数据→二进制原码→二进制反码→位移运算→二进制反码→二进制原码→特定进制数据
术右移==”
无符号右移:
语法:
操作数 >> 移动位数
举例:
unsigned char a = 3 >> 3;//0
演示:
有符号右移:
语法:
操作数 >> 移动位数
演示:
char a = -3 >> 3;// -1
演示:
关于移位运算过程:
原数据→二进制原码→二进制反码→位移运算→二进制反码→二进制原码→特定进制数据