在C语言中,提供了许多的操作符,分为算术操作符、移位操作符、关系操作符、逻辑操作符、单目操作符、双目操作符、三目操作符等,那么这些操作符都是什么呢?都怎么用的呢,下面让我们一起来看看吧!
一、算术操作符:
算术操作符可以说是最基本的操作符了,它包含加、减、乘、除以及取模运算。
//算术操作符
#include<stdio.h>
int main()
{
int a = 10 + 20;//加
int b = 20 - 10;//减
int c = 2 * 3;//乘
int d = 10 / 2;//除
int e = 10 % 2;//取模
printf("%d\n", a);//打印结果为:30
printf("%d\n", b);//打印结果为:10
printf("%d\n", c);//打印结果为:6
printf("%d\n", d);//打印结果为:5
printf("%d\n", e);//打印结果为:0
return 0;
}
这里面要说的可能是/和%这两个操作符了。
/:这个操作符功能是除法运算,但是在C语言中,除法还分为整数除法和小数除法。想执行整除除法时,左右两个操作数必须是整数,执行小数除法时,左右两个操作数有一个小数即可。
这里说明一下操作数。操作数就是操作符作用的数值,拿10+20举例,+是操作符,10和20就是操作数。
%:这个操作数功能是取模运算。在C语言中,这个操作符的左右两个操作数必须是整数,否则编译器报错。
除法运算和取模运算:在数值计算中,除法运算的结果是商,取模运算的结果是余数。
二、移位操作符:
//移位操作符
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = a << 2;//a左移两位
int d = b >> 1;//b右移一位
printf("%d\n", a);//打印结果为:10
printf("%d\n", b);//打印结果为:20
printf("%d\n", c);//打印结果为:40
printf("%d\n", d);//打印结果为:10
return 0;
}
从上面的结果可以看出,移位操作数并不会改变操作数,说白了,上述代码中a和b该是几还是几,并不会因为移位操作数就改变了。
移位操作符的使用:
移位操作符分为左移操作符和右移操作符,并且移位操作符移动的是二进制位,也就是说,想使用移位操作符之前要把数值转换成二进制。左移操作符就是将整体的二进制位的向左移动,低位补0即可,具体如下:
int a = 10 << 2;
10的二进制位:00000000 00000000 00000000 00001010
向左移动两个二进制位:00000000 00000000 00000000 00101000,将这个数转换成十进制就是40。
对于右移操作符,就有一点麻烦了,右移操作符分为逻辑移位和算术移位。
逻辑移位就是左边补0,右边丢弃。
算术移位就是左边补高位,右边丢弃。
int a = 10 >> 2;
10的二进制位:00000000 00000000 00000000 00001010
向右移动两个二进制位:00000000 00000000 00000000 00000010,将这个数转换为十进制就是2。
int b = -10 >> 3;
-10的二进制位原码:10000000 00000000 00000000 00001010
-10的二进制位反码:11111111 11111111 11111111 11110101
-10的二进制位补码:11111111 11111111 11111111 11110110
向右移动三个二进制位后的补码:11111111 11111111 11111111 11111110
向右移动三个二进制位后的反码:11111111 11111111 11111111 11111101
向右移动三个二进制位后的原码:100000000 00000000 00000000 00000010,将这个数转换为十进制就是-2。
这里的原码、反码、补码相互转换具体可以参考我的另一篇文章:一次讲透原码、反码和补码_爱吃柠檬呀的博客-CSDN博客
所以我们得出,VS编译器中采用的是算术移位。
三、位操作符:
//位操作符
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = a & b;//按位与
int d = a | b;//按位或
int e = a ^ b;//按位异或
printf("%d\n", c);//打印结果为:0
printf("%d\n", d);//打印结果为:30
printf("%d\n", e);//打印结果为:30
return 0;
}
与移位操作符相同,位操作符也是针对二进制为计算的。对于按位与&,计算方法是有0为0,全1为1。按位或|,计算方法是有1为1,全0为0。按位异或^,计算方法是相同为0,不同为1。
我本人对位操作符的计算方法是这样记忆的:
先把0想象成假(其实C语言中0就是假),把1想象成真(C语言中非0表示真),之后按位与可以理解为“和”、“全都”,也就是全都是真的才可以。按位或理解为“两个都行”,就想是有一个真就行。按位异或理解为两个位不相同才为真,所以相同就是假。
计算10与20的按位与、按位或和按位异或:
10的二进制位: 00000000 00000000 00000000 00001010
20的二进制位: 00000000 00000000 00000000 00010100
10 & 20的结果:00000000 00000000 00000000 00000000 —— 结果是0
10 | 20的结果: 00000000 00000000 00000000 00011110 —— 结果是30
10 ^ 20的结果: 00000000 00000000 00000000 00011110 —— 结果是30
四、复合操作符:
复合操作符就是算术操作符和复制操作符的结合。
赋值操作符:=
比较运算符:==
//复合运算符
#include<stdio.h>
int main()
{
int a = 0;
a += 10;//相当于a = a + 10
printf("%d\n", a);//打印结果为:10
a -= 20;//相当于a = a - 10
printf("%d\n", a);//打印结果为:-10
a *= 2;//相当于a = a * 10
printf("%d\n", a);//打印结果为:-20
a /= 3;//相当于a = a / 10
printf("%d\n", a);//打印结果为:-6
a %= 1;//相当于a = a % 10
printf("%d\n", a);//打印结果为:0
a <<= 2;//相当于a = a << 10
printf("%d\n", a);//打印结果为:0
a >>= 3;//相当于a = a >> 10
printf("%d\n", a);//打印结果为:0
a &= 5;//相当于a = a & 10
printf("%d\n", a);//打印结果为:0
a |= 10;//相当于a = a | 10
printf("%d\n", a);//打印结果为:10
a ^= 8;//相当于a = a ^ 10
printf("%d\n", a);//打印结果为:2
return 0;
}
五、单目操作符:
单目操作符就是只有一个操作数的操作符。
! //逻辑反操作
- //负值
+ //正值
& //取地址
sizeof //求操作数的类型长度(以字节为单位)
~ //对一个数的二进制按位取反
-- //前置、后置减减
++ //前置、后置加加
* //间接访问操作符(解引用操作符)
(强制类型转换) //强制类型转换
所有的单目操作符就是这些了,单目操作符的优先级都比较高,这里就不一一阐述了,想了解更多,可以参考我的另一篇文章:单目运算符详解_爱吃柠檬呀的博客-CSDN博客
六、关系操作符:
这些操作符很好理解,就是比较两个数的关系的。
//关系操作符
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 10 == 20;
printf("%d\n", c);//打印结果为0
int d = 10 != 20;
printf("%d\n", d);//打印结果为1
int e = 10 >= 20;
printf("%d\n", e);//打印结果为0
int f = 10 <= 20;
printf("%d\n", f);//打印结果为1
return 0;
}
关系操作符的结果是bool类型的,如果为真就返回1,假就返回0。
七、逻辑操作符:
逻辑操作符的返回值也是bool类型的,如果表达式为真就返回1,否则就返回0。
//逻辑操作符
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 0;
int d = NULL;//在C语言中,NULL是空指针的意思,也表示假
int e = a && b;
printf("%d\n", e);//打印结果为:1
int f = a && c;
printf("%d\n", f);//打印结果为:0
int g = c && d;
printf("%d\n", g);//打印结果为:0
int h = a || b;
printf("%d\n", h);//打印结果为:1
int i = a || c;
printf("%d\n", i);//打印结果为:1
int j = c || d;
printf("%d\n", j);//打印结果为:0
return 0;
}
这里还需要补充短路现象。
短路现象就是对于逻辑与来说,只要前面表达式为假,整体就为假,程序不会向后执行。对于逻辑或,只要前面的表达式为真,整体就为真,程序不会向后执行。
//短路现象
#include<stdio.h>
int main()
{
int a = 1;
int b = -1;
int c = 0;
int d = (c--) && ((a ^ c) + (b * (a + c)) % (b + c));
int e = (++a) || ((a--) / (b + (d--)) << (b + 10) & (a + d));
printf("%d\n", a);//打印结果为:2
printf("%d\n", b);//打印结果为:-1
printf("%d\n", c);//打印结果为:-1
printf("%d\n", d);//打印结果为:0
printf("%d\n", e);//打印结果为:1
return 0;
}
上面的代码中,我们不看&&和||后面的表达式多复杂,只要&&前面的表达式为假,后面就不计算,||前面的表达式为真,后面就不计算。
八、条件操作符:
条件操作符具体语法格式如下:
exp1 > exp2? exp1 : exp2;
//如果exp1大于exp2,执行exp1,否则执行exp2
该操作符可以代替最简单的条件分支语句,代码如下:
//判断两个数的大小
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
printf("a和b的最大值是:%d\n", a > b ? a : b);
return 0;
}
九、逗号表达式:
逗号表达式是优先级最低的操作符,语法格式如下:
exp1, exp2, exp3, ..., expn;
//从左向右依次计算,表达式expn的结果就是整个表达式的结果
//逗号表达式
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
printf("%d\n", c);//打印结果为13
return 0;
}
十、操作符优先级:
操作符的优先级和结合性大部分情况下决定了唯一的运算路径,但是只有操作符和结合性并不能确定唯一的运算路径。
操作符 | 描述 | 用法 | 结果类型 | 结合性 | 是否控制求值顺序 |
() | 聚组 | (表达式) | 与表达式相同 | N/A | 否 |
() | 函数调用 | rexp(rexp, ...,rexp) | rexp | L-R | 否 |
[] | 下标引用 | rexp[rexp] | lexp | L-R | 否 |
. | 访问结构成员 | lexp.member_name | lexp | L-R | 否 |
-> | 访问结构指针成员 | rexp->memeber_name | lexp | L-R | 否 |
++ | 后缀自增 | lexp++ | rexp | L-R | 否 |
-- | 后缀自减 | lexp-- | rexp | L-R | 否 |
! | 逻辑反 | !rexp | rexp | R-L | 否 |
~ | 按位取反 | ~rexp | rexp | R-L | 否 |
- | 单目,表示正值 | +rexp | rexp | R-L | 否 |
+ | 单目,表示负值 | -rexp | rexp | R-L | 否 |
++ | 前缀自增 | ++lexp | rexp | R-L | 否 |
-- | 前缀自减 | --lexp | rexp | R-L | 否 |
* | 间接访问 | *rexp | lexp | R-L | 否 |
& | 取地址 | &lexp | rexp | R-L | 否 |
sizeof | 取其长度,以字节表示 | sizeof rexp sizeof(类型) | rexp | R-L | 否 |
(类型) | 类型转换 | (类型)rexp | rexp | R-L | 否 |
* | 乘法 | rexp * rexp | rexp | L-R | 否 |
/ | 除法 | rexp / rexp | rexp | L-R | 否 |
% | 整数取余 | rexp % rexp | rexp | L-R | 否 |
+ | 加法 | rexp + rexp | rexp | L-R | 否 |
- | 减法 | rexp - rexp | rexp | L-R | 否 |
<< | 左移位 | rexp | rexp | L-R | 否 |
>> | 右移位 | rexp >> rexp | rexp | L-R | 否 |
> | 大于 | rexp > rexp | rexp | L-R | 否 |
>= | 大于等于 | rexp >= rexp | rexp | L-R | 否 |
< | 小于 | rexp < rexp | rexp | L-R | 否 |
<= | 小于等于 | rexp | rexp | L-R | 否 |
== | 等于 | rexp == rexp | rexp | L-R | 否 |
!= | 不等于 | rexp != rexp | rexp | L-R | 否 |
& | 位与 | rexp & rexp | rexp | L-R | 否 |
^ | 位异或 | rexp ^ rexp | rexp | L-R | 否 |
| | 位或 | rexp | rexp | rexp | L-R | 否 |
&& | 逻辑与 | rexp && rexp | rexp | L-R | 是 |
|| | 逻辑或 | rexp || rexp | rexp | L-R | 是 |
?: | 条件操作符 | rexp ? rexp : rexp | rexp | N/A | 是 |
= | 赋值 | lexp = rexp | rexp | R-L | 否 |
+= | 以...加 | lexp += rexp | rexp | R-L | 否 |
-= | 以...减 | lexp -= rexp | rexp | R-L | 否 |
*= | 以...乘 | lexp *= rexp | rexp | R-L | 否 |
/= | 以...除 | lexp /= rexp | rexp | R-L | 否 |
%= | 以...取模 | lexp %= rexp | rexp | R-L | 否 |
<<= | 以...左移 | lexp | rexp | R-L | 否 |
>>= | 以...右移 | lexp >>= rexp | rexp | R-L | 否 |
&= | 以...与 | lexp &= rexp | rexp | R-L | 否 |
^= | 以...异或 | lexp ^= rexp | rexp | R-L | 否 |
|= | 以...或 | lexp |= rexp | rexp | R-L | 否 |
, | 逗号 | rexp, rexp | rexp | L-R | 是 |
以上就是我的分享啦,写的不好,请多多见谅!