C语言操作符(下)

一、移位操作符

注:以下关于位的操作符讲解都是在32位机器平台下进行的。

1.左移操作符

<<:左移操作符,也就是把所有的二进制位向左移动对应的位数。规则是:左边移出(丢弃),右边补0。例如:

#include <stdio.h>
int main()
{
	int num = 10;
	int n = num << 3;
	printf("n = %d\n", n);
	printf("num = %d\n", num);
	return 0;
}

运行结果:
在这里插入图片描述在这里插入图片描述我们知道数据在计算机中都是以补码的形式来存储的,所以num==10在左移3位后得到的还是补码(00000000 00000000 00000000 01010000),又因为正整数的原反补码是一样的,所以正整数10左移三位后得到的二进制数转换成十进制数为80。且num的值是没有改变的,通过输出结果可以看出。

2.右移操作符

>>:右移操作符,把所有的二进制位向右移动对应的位数。右移分为逻辑右移算术右移
逻辑右移:左边用0填充,右边移出(丢弃)
算术右移:左边用原该值的符号位填充,右边移出(丢弃)

Ⅰ.算术右移

#include <stdio.h>
int main()
{
	int num = 10;
	int n = num >> 1;
	printf("n = %d\n", n);
	printf("num = %d\n", num);
	return 0;
}

运行结果:
在这里插入图片描述在这里插入图片描述这里得到的运行结果是n==5,但是你看不出是逻辑右移还是算术右移,因为对于正整数,不管是逻辑右移还算术右移左边都是补0。我们再看一段代码:

#include <stdio.h>
int main()
{
	int num = -1;
	int n = num >> 1;
	printf("n = %d\n", n);
	printf("num = %d\n", num);
	return 0;
}

运行结果:
在这里插入图片描述在这里插入图片描述在这里插入图片描述通过上面的输出结果可以看出,num==-1右移一位最高位补的是1,所以这里是算术右移。在我使用的VS2022这个编译器上采用的就是算术右移(大部分编译器都是算术右移)。

Ⅱ.逻辑右移

逻辑右移就不用考虑符号位了,不管是正整数还是负整数逻辑右移最高位补的都是0。
在这里插入图片描述在这里插入图片描述-1和10通过逻辑右移一位后得到的还是补码,只是逻辑右移后最高位补的是0,不管是正整数还是负整数,符号位都变成了0,都会被当成正整数,而正整数的原反补码相同。以有符号十进制数打印出来的结果就是:2147483647和5。

注意:移位操作符的操作数只能是整数
警告:对于移位运算符,不要移动负数位,这种是标准未定义的(就像10>>-1,这种是未定义的)

3.移位的复合赋值运算符

我们讲过复合赋值运算符,就是相应的算术运算符结合赋值运算符的一种简化,那么对于移位操作符也是有复合赋值运算符的:

#include <stdio.h>
int main()
{
	int num1 = 10;
	int num2 = 20;
	num1 >>= 1;
	num2 <<= 1;
	printf("num1 = %d\n", num1);
	printf("num2 = %d\n", num2);
	return 0;
}

运行结果:
在这里插入图片描述上面的 num1>>=1 其实就是 num1=num1>>1 的意思,num2<<=1即num2=num2<<1。

二、位操作符

1.按位与(&)

通过一段代码来说明位与操作符

#include <stdio.h>
int main()
{
	int n = -10;
	int m = 5;
	printf("%d\n", n & m);
	return 0;
}

运行结果:
在这里插入图片描述按位与就是将两个整数所有对应的二进制位进行逐一比较,同1则为1有0则为0,得到的二进制数即为按位与后的结果。就像上面的 -10 & 5:(注意:整数在计算机中存放的是补码)
在这里插入图片描述所以n(-10) & m(5)的结果就为00000000 00000000 00000000 00000100,换算成十进制的整数就为4。

2.按位或(|)

按位或就是将两个整数所有对应的二进制位进行逐一比较,同0则为0有1则为1,得到的二进制数即为按位或后的结果。

#include <stdio.h>
int main()
{
	int n = -7;
	int m = 12;
	printf("%d\n", n | m);
	return 0;
}

运行结果:
在这里插入图片描述在这里插入图片描述所以n(-7) | m(12)的结果就为11111111 11111111 11111111 11111101,按位或得到的这个结果还是补码,最高位是符号位,换算成10进制的整数就为-3。

3.按位异或(^)

按位异或的意思就是:将两个整数所有对应的二进制位进行逐一比较,相同为0,相异为1。

#include <stdio.h>
int main()
{
	int n = 9;
	int m = -13;
	printf("%d\n", n ^ m);
	return 0;
}

运行结果:
在这里插入图片描述在这里插入图片描述所以n(9) ^ m(-13)的结果就为:11111111 11111111 11111111 11111010,按位异或得到的结果还是补码,换算成十进制的整数就为-6。

4.按位取反(~)

按位取反就是将整数的所有二进制位(bit):是1的变为0,是0的变为1(包括符号位)。注意:数据在计算机中存储的是补码。

#include <stdio.h>
int main()
{
	int a = 17;
	printf("%d\n", ~a);
	return 0;
}

运行结果:
在这里插入图片描述在这里插入图片描述按位取反是位操作符中唯一的单目操作符。需要注意:按位取反是所有的二进制位都要取反(0变1,1变0),包括符号位。而原码变成反码的取反是符号位不变,数值位按位取反。

5.位的复合赋值运算符

同样的,对于位操作符也是有复合赋值运算符的:

#include <stdio.h>
int main()
{
	int a = 10;
	int b = 13;
	int c = -5;
	a &= 1;
	printf("%d\n", a);
	b |= 1;
	printf("%d\n", b);
	c ^= 1;
	printf("%d\n", c);
	return 0;
}

运行结果:
在这里插入图片描述上面的a &= 1、b |= 1、c ^= 1意思分别是a = a&1、b = b|1、c = c^1。就是位操作符结合赋值操作符的简化。注意:对于上述位操作符的操作数必须是整数

三、操作符的结合性和优先级

C语言的操作符有2个重要的属性:优先级、结合性。这两个属性决定了表达式求值的计算顺序。

1.优先级

优先级指的是:如果一个表达式包含多个运算符,哪个运算符应该优先执行。各种运算符的优先级是不一样的。

2 + 3 * 4

上面示例中,表达式2 + 3*4里面既有加法运算符(+),又有乘法运算符(*)。由于乘法的优先级高于加法,所以会先计算3*4,而不是先计算2+3。

2.结合性

如果两个运算符的优先级相同,优先级没办法确定要先计算哪个,这个时候就要看结合性了,则根据运算符是左结合,还是右结合,决定执行顺序。即当一个操作数两侧的运算符优先级相同时,要看操作数与操作符的结合顺序。大部分运算符是左结合(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符(=)。

5 * 4 / 2

上面示例中,* 和 / 的优先级是相同的,所以对于中间的操作数4就要看与操作符 * 和 / 的结合性了,因为 * 和 / 都是左结合性,按照从左往右的结合方向。所以4先和*结合,也就是先执行5*4的运算,再执行 /2 的运算。

3.操作符优先级表

下表整理了运算符的优先级和结合性:
在这里插入图片描述

文章若有不足的地方,欢迎小伙伴们在评论区指正哦!

  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米饭「」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值