- 一、算术操作符
- 二、移位操作符
- 三、位操作符
- 四、赋值操作符
- 五、单目操作符
- 六、关系操作
- 七、逻辑操作符
- 八、条件操作符
- 九、逗号表达式
算术操作符包括:加号(+),减号(-),乘号(*),除号(/),取模(%)。
大家都非常了解这些操作符,但是有一些注意的地方需要说明一下。
除号(/)
1/5打印结果是0.这里就要说一下为什么结果是0,而不是0.2呢?
1/5,除号两边的两个操作符是整数,所以这里进行的是整数除法,1/5就是商0余1.
如果换成6/5打印结果就是1,这里就是商1余1.这就是整数除法。
那么我们如何改正了?
想要打印出浮点数,除号两端的操作数最少要有一个是操作符,这样执行的就是浮点数的除法。
取模(%)
取模(%)操作符的两个操作数必须是整数。
返回的是整除之后的余数。
(<<)左移操作符
(>>)右移操作符
左移操作符
右移操作符
右移操作符分为两种:
算术右移,右边丢弃,左边补原符号位。
逻辑右移,右边丢弃,左边补0。
a的二进制序列:
00000000 00000000 00000000 00000010
向右移动一位:
00000000 00000000 00000000 00000001
由于a是正数,所以不管是逻辑运算,还是算术运算,左边都是补0,所以得到的b的值就是1。
如果是负数呢?那又会有咋样的变化呢?
负数:-1
说到这里必须交代一个知识点,
整数的二进制的表示形式有三种,分别是原码,反码,补码。
原码:直接根据数据写出的二进制序列就是原码。
反码:原码的符号位不变,其他位按位取反就是反码。
补码:反码+1,就是补码。
-1的二进制序列:
原码:10000000 00000000 00000000 00000001
反码:111111111 111111111 111111111 111111110
补码:111111111 111111111 111111111 111111111
现在我们把-1向右移动一位,如果你当前的编译器采用的是算术右移,右边丢弃,左边补原符号位。
如果是逻辑右移,右边丢弃,左边补0。
三、位操作符注:把a向右移动一位,a的值是不变的,我们只是把a向右移动一位的值放到b里面,a的值是不变的。
(&)按位与
(|)按位或
(^)按位异或
按位与
#includeint main() { int a = 3; int b = 5; //& ➡️ 按(2进制)位与 //a ➡️ 00000000 00000000 00000000 00000011 //b ➡️ 00000000 00000000 00000000 00000101 //对应的2进制位按位与,只要有0,结果就是0,两个都是1结果才为1 //按位与后的结果 ➡️ 00000000 00000000 00000000 00000001 int c = a & b; printf("%dn", c);//打印结果为1 return 0; }
按位或
#includeint main() { int a = 3; int b = 5; //| ➡️ 按(2进制)位或 //a ➡️ 00000000 00000000 00000000 00000011 //b ➡️ 00000000 00000000 00000000 00000101 //对应的2进制位按位或,只要有1,结果就是1,两个都是0结果才为0 //按位与后的结果 ➡️ 00000000 00000000 00000000 00000111 int c = a | b; printf("%dn", c);//打印结果为7 return 0; }
按位异或
#includeint main() { int a = 3; int b = 5; //^ ➡️ 按(2进制)位异或或 //a ➡️ 00000000 00000000 00000000 00000011 //b ➡️ 00000000 00000000 00000000 00000101 //对应的2进制位按位异或,相同为0,相异为1 //按位与后的结果 ➡️ 00000000 00000000 00000000 00000110 int c = a ^ b; printf("%dn", c); return 0; }
四、赋值操作符注:这三个操作符的操作数必须都是整数。
(=)赋值操作符(+= -= *= /= %= <<= >>= &= |= ^=)复合赋值操作符
赋值操作符
一个等号(=)叫做赋值,两个等号(==)叫做判断
#includeint main() { int a = 0; int b = 1; if (a == b) { printf("hehen"); } else { printf("hahan"); } return 0; }
注:字符串比较是不可以使用==来比较
复合操作符
#include五、单目操作符int main() { int a = 10; a += 10; printf("%d", a); return 0; }
! 逻辑反操作
- 负值
+ 正值
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
- - 前置 后置 - -
++ 前置 后置 ++
!逻辑反操作符
#includeint main() { int a = 5; if (a) { //a为真时打印hehe printf("hehen"); } if (!a) { //a为假时打印haha printf("hahan"); } return 0; }
负值与正值
#includeint main() { int a = 2; a = -a; printf("%dn", a);//打印-2 return 0; }
#includeint main() { int a = 2; a = +a; printf("%dn", a);//打印2 return 0; }
a = +a这种写法可以忽略,没什么用。
sizeof 操作数的类型长度
计算一个类型或者变量所占内存的大小。
#includeint main() { int a = 5; printf("%dn", sizeof(a));//打印4 printf("%dn", sizeof(int));//打印4 return 0; }
a的类型是int,sizeof(a)可以计算a所占空间的大小,单位是字节.
sizeof是一个操作符,不是函数.
打印的结果是2和5,为什么呢?
a+2虽然是一个int类型的值,但是c不会因为放了这样一个值空间就变大,而sizeof求的是c所占空间字节的大小,所以第一个打印的是2.
为什么第二个是5呢?因为sizeof内部存放的表达式是不会参与运算的,所以c的值不变。
~ 对一个数的二进制按位取反
#includeint main() { int a = -1; int b = ~a; //~对一个数的二进制位按位取反 //-1的补码11111111 11111111 11111111 11111111 //b的值为00000000 00000000 00000000 00000000 printf("%dn",b);//打印0 return 0; }
- -前置、后置- -
++前置、后置++
#includeint main() { int a = 10; printf("%dn", ++a);//打印11 printf("%dn", a++);//打印11 return 0; }
#includeint main() { int a = 10; printf("%dn", --a);//打印9 printf("%dn", a--);//打印9 return 0; }
++前置,先++,后使用。
后置++,先使用,后++。
- -前置、后置- -同理。
(>) 大于操作符
(>=) 大于等于操作符
(<) 小于操作符
(!=) 用于测试”不等于“
(==) 用于测试”等于“
关系表达式通常返回0或1,表示真伪。c语言中,0表示伪,所有非零值表示真。比如,99 > 1返回1,1 > 99返回0。注意,相等运算符==与赋值运算符=是两个不一样的运算符,不要混淆。
七、逻辑操作符&& 逻辑与
|| 逻辑或
逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。
因为a++是后置++,所以先使用,后++,a为0,根据短路效应,&&前面的值如果为假后面的表达式就不进行计算了,所以最终的结果为1,2,3,4。
这次我们把a的值改为1,因为a为真,根据短路效应,|| 前面的值如果为真后面的表达式就不进行计算了,所以最终的结果为2,3,3,5。
八、条件操作符exp1 ? exp2 : exp3
条件操作符也叫三目操作符
逗号表达式,从左向右依次计算,整个表达式的结果是最后一个表达式的结果。
所以说c = 5,a = a + 3结果是5,b=a-4结果是3,c+=6结果是11.不能只算最后一个表达式的结果,一定要从左向右一次进行计算。



