前情回顾:在2级的时候,我们学习的有:占位符、输出函数、输入变量......
概念
什么是运算符?
答:运算符是用来对数据进行各种运算的符号,用于执行数学计算、逻辑判断、位操作等操作。在C语言中,运算符分为:算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符。
算术运算符
加法(+):用于两数相加。例如 int a = 4+ 5;,结果 a 的值为 9
减法(-):用于两数相减。例如 int a = 5 - 4;,结果 a 的值为 1
乘法(*):用于两数相乘。例如 int a = 4 * 5;,结果 a 的值为 20
除法(/):用于两数相除,结果为商。例如 int a = 6 / 4;,结果 a 的值为 1
取余(%):也叫模运算,用于两数相除,结果为余数。例如 int a = 6 % 4;,结果 a 的值为 2
注意:
除法/的运算结果和运算对象的数据类型有关。
假设两个数都是int,则商就是int
例如:16/5->3 6/4->1
假设其中一个或两个都是浮点型数据,则商就是浮点型
例如:16/5.0->3.20000 6.0/4->1.50000
取余%只能对整数,结果是余数,余数的符号与除数相同。
例如:13%3->1 13%-3->1 -13%3->-1 6%4->2 6%-4->2 -6%4->2
程序代码:
#include <stdio.h>
int main()
{
printf("16/5=%d\n",16/5);
printf("16/5.0=%lf\n",16/5.0);
printf("13%%3=%d\n",13%3); //如果想输出%这个字符,需要使用%%
printf("13%%-3=%d\n",13%-3);
printf("-13%%3=%d\n",-13%3);
return 0;
}
运行结果:
关系运算符
关系运算符常用在条件判断,循环结构。返回的结果只有真或假,而在C语言中,真用整型1来表示,假由整型0来表示。
小于(<):x<y。用于判断x是否小于y。例如 int a = (4<5);,结果 a 的值为 1(真)
大于(>):x>y。用于判断x是否大于y。例如 int a = (4>5);,结果 a 的值为 0(假)
等于(==):x==y。用于判断x是否等于y。例如 int a = (4==5);,结果 a 的值为 0(假)
不等于(!=):x==y。用于判断x是否不等于y。例如 int a = (4!=5);,结果 a 的值为 1(真)
小于等于(<=):x<=y。用于判断x是否小于或等于y。例如 int a = (4<=5);,结果 a 的值为 1(真)
大于等于(>=):x>=y。用于判断x是否大于或等于y。例如 int a = (4>=5);,结果 a 的值为 0(假)
程序代码:
#include <stdio.h>
int main()
{
printf("4<5=%d\n",4<5);
printf("4>5=%d\n",4>5);
printf("(4==5)=%d\n",4==5);
printf("(4!=5)=%d\n",4!=5);
printf("4<=5=%d\n",4<=5);
printf("4>=5=%d\n",4>=5);
return 0;
}
结果:
自增和自减运算符
前自增(++a):先将a的值加 1
,再使用。int a=1,b; int b = ++a; 结果 b 的值为 2 ;a的值为2
后自增(a++):先使用 a
的值,再将其加 1。
int a=1,b; int b = a++; 结果 b 的值为 1 ;a的值为2
前自减(--a):先将a的值减 1
,再使用。int a=1,b; int b = --a; 结果 b 的值为 0 ;a的值为0
后自减(a--):先使用 a
的值,再将其减 1。
int a=1,b; int b = a--; 结果 b 的值为 1 ;a的值为0
自增或自减最终a的值都会+1或-1。唯一区别是前置和后置。
技巧:看a的位置。
如b=a++,a最靠近b,所以b=a,然后a=a+1。
再如前置b=++a,a离b最远,所以a=a+1,然后b=a。
#include <stdio.h>
int main()
{
int a1 = 1;
int b1 = ++a1; //前自增
printf("a1=%d,b1=%d\n",a1,b1);
int a2 = 1;
int b2 = a2++; //后自增
printf("a2=%d,b2=%d\n",a2,b2);
return 0;
}
结果:
逻辑运算符
非(!):对操作数取反,!假变真,!真变假。例如:int a = !(4>5),虽然4>5为假,但经过非变真。所以结果 a 的值为 1(真)
逻辑与(&&):只有当两个操作数都为真时,结果才为真。0&&1= 0、1&&0 = 0、0&&0=0、1&&1=1。例如:int a = (4>5) && (2<3),结果 a 的值为0(假) 原因:4>5=0,2<3=1,而0&&1= 0
小知识:a++和a--也可以使用到逻辑运算中(除了1表示真,还有大于0的数也表示真)
程序代码:
#include <stdio.h>
int main()
{
int a1 = 1;
int b1 = (4>5) && (a1++); //0,因为4>5假,不执行a1++
printf("b1=%d,a1=%d\n",b1,a1);
int a2 = 1;
int b2 = (4<5) && (a2++); //1,1&&a1=1(真)。因为a2++是前自增,是先使用a2值,而不是a2++后的值,并且会执行a2++
printf("b2=%d,a2=%d\n",b2,a2);
return 0;
}
这里值得注意的是:假如&&运算时,检测到左边为假,则不会检测右边,结果直接为假!
例如:
int a1=1;
int b1 = (4>5) && (a1++);
在这里&&运算检测到4>5为假,不会再执行a1++这一操作,所以a1自增失败,值还是1
口诀:逻辑与,左假,右不执行
结果:
逻辑或(||):当一个或两个操作数都为真时,结果就为真。0||1= 1、1||0 = 1、0||0=0、1||1=1。例如:int a = (4>5) || (2<3),结果 a 的值为1(真) 原因:4>5=0,2<3=1,而0||1= 1。
这里值得注意的是:假如||运算时,检测到左边为真,则不会检测右边,结果直接为真!
例如:
int a1=0;
int b1 = (2<3) || (a1++);
在这里||运算检测到2<3为真,不会再执行a1++这一操作,所以a1自增失败,值还是0。
口诀:逻辑或,左真,右不执行
#include <stdio.h>
int main()
{
int a1 = 0;
int b1 = (2<3) || (a1++); //1, 1||a1=1(真),不执行a1++
printf("b1=%d,a1=%d\n",b1,a1);
int a2 = 0;
int b2 = (2>3) || (a2++); //0, 0||a2=1(真),然后执行a2++
printf("b2=%d,a2=%d\n",b2,a2);
return 0;
}
结果:
赋值运算符
在有些时候,我们需要改变变量的值,希望它变成2倍、3倍或者减少一半等等,我们可以用一种赋值运算符进行数字运算后的赋值。例如:
int a = 2; 将2赋值给int类型变量a,结果 a 的值为2
a += 3; 等价于 a = a+3,结果 a 的值为 2+3=5
a *= 2; 等价于 a = a*2,结果 a 的值为 5*2=10
a /= 2; 等价于 a = a/2,结果 a 的值为 10/2=5
a -= 3; 等价于 a = a-3;,结果 a 的值为 5-3=2
位运算符
位运算符常用于二进制数的处理,像是在单片机编程中常会用到。首先我们需要先了解进制转换、编码形式。相关知识,可以去1级重新回顾一下。
除此之外,还需要了解与、或和异或。
与:0&0=0、1&0=0、0&1=0、1&1=1
口诀:与运算,遇0变0,遇1不变
或:0|0=0、1|0=1、0|1=1、1&1=1
口诀:或运算,遇0不变,遇1变1
异或:0^0=0、1^0=1、0^1=1、1^1=0
口诀:异或运算,相同为0,不同为1
按位与(&):将两个数转为二进制,对应位都进行与运算,都为 1 时结果为 1,否则为 0。
例如:
(1)int a= 5; 5转二进制为0101,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 0101
(2)int b= 9; 9转二进制为1001,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 1001
(3)进行 a & b。a和b每一位对应与运算,根据口诀,前面不变,与运算的只有0101&1001,结果得0001,最终结果为0000 0000 0000 0000 0000 0000 0000 0001
#include <stdio.h>
int main()
{
int a=5,b=9;
printf("5&9=%d",a&b);
return 0;
}
结果:
按位或(|):将两个数转为二进制,对应位都进行或运算,都为 0 时结果为 0,否则为 1。
例如:
(1)int a= 5; 5转二进制为0101,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 0101
(2)int b= 9; 9转二进制为1001,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 1001
(3)进行 a | b,a和b每一位对应或运算,根据口诀,前面不变,或运算的只有0101|1001,结果得1101。最终结果为0000 0000 0000 0000 0000 0000 0000 1101
#include <stdio.h>
int main()
{
int a=5,b=9;
printf("5|9=%d",a|b);
return 0;
}
结果:
按位异或(^):将两个数转为二进制,对应位都进行异或运算,相同为 0,不同为 1。
例如:
(1)int a= 5; 5转二进制为0101,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 0101
(2)int b= 9; 9转二进制为1001,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 1001
(3)进行 a ^ b,a和b每一位对应异或运算,根据口诀,前面不变。异或运算的只有0101^1001,结果得1100。最终结果为0000 0000 0000 0000 0000 0000 0000 1100
#include <stdio.h>
int main()
{
int a=5,b=9;
printf("5^9=%d",a^b);
return 0;
}
结果:
按位取反(~):将操作数转为二进制,对应位都进行取反,0变1,1变0。
例如:
(1)int a= 5; 5转二进制为0101,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 0101
(2)进行~a,按位取反(0变1,1变0),结果为1111 1111 1111 1111 1111 1111 1111 1010。因为int类型数据采用补码形式,所以将其转成原码形式:1000 0000 0000 0000 0000 0000 0000 0110
最高符号位为1,转十进制:-6
#include <stdio.h>
int main()
{
int a=5;
printf("~a=%d",~a);
return 0;
}
结果:
左移运算符(<<):将操作数转为二进制,不管有无符号数都是整体左移n位(<<1左移1位,<<2左移2位...),并且低位补0
例如:
(1)int a= 5; 5转二进制为0101,因为int是32位的,将其正数扩充为32位:0000 0000 0000 0000 0000 0000 0000 0101
(2)进行a<<1,也就是二进制数左移动,并且低位补0,也就是0000 0000 0000 0000 0000 0000 0000 1010
#include <stdio.h>
int main()
{
int a=5;
printf("a<<1=%d",a<<1);
return 0;
}
结果:
右移运算符(>>):将操作数转为二进制,有符号数的符号位不动,整体右移,正数高位补0,负数高位补1;无符号数整体右移,高位补0。
例如:0101
(1)int a=-5; a转补码形式为1,1011,因为int是32位的,需要扩充为32位:1111 1111 1111 1111 1111 1111 1111 1011。(原码转补码:除符号位其他位取反,再加1)
(2)进行a>>1,除符号位,剩余位右移,高位补1(补码右移,正数补0,负数补1)。右移结果:1111 1111 1111 1111 1111 1111 1111 1101 接着转成原码形式:1000 0000 0000 0000 0000 0000 0000 0011 (补码转原码--除符号位其他位取反,再加1),转换成十进制就是 -3
#include <stdio.h>
int main()
{
int a=-5;
printf("a>>1=%d",a>>1);
return 0;
}
结果:
运算符的优先级
以下是运算符共同使用的情况下的优先级,优先级越高越先执行,但是也不需要刻意背下来,常用就会熟悉。
在该系列中,文章的前部分采用简短的白话文讲解用法,而后部分采用更深入的角度讲解原理。思考是人类的结晶~如果你觉得有用,给我个点赞、收藏+关注哦~持续更新