C语言:简析移位操作符与位操作符

1.预备知识:原码、反码、补码

原码、反码、补码是3种整数二进制表示方式。计算机中有规定:正整数三种类型均相同、负整数三种类型各不相同。但是要注意的一点的是:三种表示方式都是32位的,无意义的位数用数字“0”来填充

1.1正整数原码、反码、补码

对于正整数,三种表示方式都是直接把十进制数进制转换为二进制数。例如:十进制数10的原码、反码、补码均为 00000............0001010(一共有32位)。

1.2负整数原码、反码、补码

1.2.1原码

负整数的原码与正整数的区别在于最高位数变成了“1”,因此,原码的最高位就可以看做是数字的“符号位”(1为负数、0为正数)。举10与-10的例子:

1.2.2反码

除了负整数的符号位,其余位数全部倒转(0变1,1变0):

1.2.3补码

补码=反码+1.

2.移位操作符

2.1左移操作符

左移操作符“<<”,先看以下代码:

int main()
{
	int a = 3;
	a = (a << 1);
	printf("%d", a);
	return 0;
}

输出结果为 6.

左移操作符的规律是:二进制数的所有位数向左移动x位,超过32位的位数舍去,右边不足的位数用0补上。以上面这个例子来说:

同时,我们发现左移操作符每操作一次就会使二进制数中的所有“1”向高位移动一位,这个作用的效果就是操作后的数是操作前的数的两倍。(   a>>x=(2^x)*a    )

2.2右移操作符

右移操作符“>>”

一般来说,右移操作符的含义是:所有二进制位向右移动x位,最右边多余的位数舍去,但最左边的符号为不改变(是1还是1,不会用0覆盖)

3.位操作符

位操作符是针对两个数或者一个数进行操作的。要注意的一点是:我们创建的整型变量,存放在内存中存放的其实是数据的补码形式(也就是说数据先加工为二进制原码再转变为补码存入内存中)

位操作符有4种类型:&(按位与)、|(按位或)、^ (按位异或)、~(按位取反),用法如下:      &..........................(有0则0,两个1才能为1)                                                                                        |............................(有1则1,两个0才能为0)                                                                                        ^...........................(相同为0,相异为1)                                                                                              ~...........................(所有0变1,1变成0)

我们可以用一些数字对这些操作符进行简单的测试:(前三种操作符都是两个数字,按位取反是一个)

有兴趣的同学可以手算一下,原码与补码之间的换算都是取反+1,也就是说:原码取反+1=补码;补码取反+1=原码。

4.题目举例

经过上述学习,我们初步了解到了移位操作符与位操作符的基本作用,现在我们通过一些题目更加深入地了解一下这些操作符的作用。

(题目1:不创建第三个变量实现两个整数的交换)

int main()
{
	int a = 6;
	int b = 4;
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	return 0;
}

这串代码的输出结果如下:

简要讲解一下它的原理:a=a^b;相当于将ab间不同的位数存储在a中,b=a^b;此时a和b的差异又变成了最初始的a了。用公式来理解 b=(a^b)^b=a^b^b=a^(b^b)=a^0=a;                                                同理,最后一行a=a^b=(a^b)^a=a^a^b=(a^a)^b=0^b=b; 这样,a和b就成功地交换了。

(题目2:求一个整数存储在内存中的二进制数中1的个数)

int main()
{
	int a = 0;
	int count = 0;
	while (1)
	{
		scanf_s("%d", &a);
		for (int i = 0; i < 32; i++)
		{
			if (a & 1 == 1)
			{
				count++;
			}
			a = a >> 1;
		}
		printf("1的个数为:%d\n", count);
		count = 0;
	}
	return 0;
}

输出结果如下:

原理是:将目标数与000........001(十进制1)按位与可以检测目标数最右边的数是不是1,如果是1的话就令count++。检测完之后,为了检测其他位数,再将目标数每次用右移操作符操作一次,这样可以丢弃检测完的数(因为二进制数有32位,所以写for循环重复32次即可)。

  • 36
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值