c语言常用操作符(2)

慈云数据 6个月前 (05-11) 技术支持 74 0

 1.移位操作

移位操作符分为

注:移位操作符的操作数只能是整数,同时移位操作符移动的是存储内存中的二进制位(也就是补码)

同时移位操作符不要移动负数位,这个是标准未定义的。

1.> 1; printf("a=%d\n", a); printf("b=%d\n", b); return 0; }

 以上代码输出结果

通过以上代码可以发现右移有除2的效果 

2.位操作符

位操作符有:

&  按位与

|    按位或

^   按位异或

~   按位取反

注:位操作符的操作数必须是整数,同时位操作符是对存储在内存中的二进制位(也就是补码)进行运算

在这不要将&和|与之前讲到的&&和||混淆 &&和||关注的是操作符两端的真假 &和|关注的是操作符两端的二进制序列

1.& 按位与

#include
int main()
{
	int a = -7;
	int b = 6;
	int c = a & b;
	printf("c=%d\n", c);
	return 0;
}

在以上代码中a&b  首先我们知道&是对操作数在内存中存储的二进制位进行运算,所以先将a和b的补码表示出来如下所示

在按位与操作符中两个操作数对应二进制位有0则为0,俩个都为1时,才为1 

所以就可得出c的补码

 最终c的结果为0

运行程序验证以上运算

2.|  按位或

#include
int main()
{
	int a = -7;
	int b = 6;
	int c = a | b;
	printf("c=%d\n", c);
	return 0;
}

将此先的代码再使用一遍,而这时将c=a | b 

 在按位或操作符中两个操作数对应二进制位有1则为1,俩个都为0时,才为0

所以就可得出c的补码

 最终c的结果为-1

运行程序验证以上运算

3.^   按位异或

#include
int main()
{
	int a = -7;
	int b = 6;
	int c = a ^ b;
	printf("c=%d\n", c);
	return 0;
}

在以上代码中用到了按位异或操作符,要得到c的结果首先要知道^的计算逻辑

在按位异或操作符中两个操作数对应二进制位不同则为1,俩个相同时,才为0

 

所以最终c输出结果为-1

运行程序验证以上运算

4.~   按位取反  

按位取反操作符是将整数的二进制位全部取反 

#include
int main()
{
	int a = -7;
	int b = 6;
	int c = a ^ b;
	int d = ~c;
	printf("d=%d\n", d);
	return 0;
}

例如在以上代码中对c按位取反 最终d输出结果为0

 运行程序验证以上运算

5.练习

练习1.一道面试题

不能创建临时变量(第三个变量),实现两个整数的交换

 

#include
int main()
{
	int a = 0;
	int b = 0;;
	scanf("%d %d", &a, &b);
	 a = a ^ b;
	 b = a ^ b;
	 a = a ^ b;
	printf("a=%d b=%d",a,b);
	return 0;
}

要理解这种方法就要再了解一下^的一些特点 

1.a^a=0

2.a^0=a

3.a^b^c=a^c^b=b^a^c=b^c^a=c^a^b=c^b^a(异或是支持交换率)

来举一些例子让我们更好理解以上特点 

 例如:3^3操作符的二进制位都相同所以异或后都为0,所以最终3^3=0

            3^0操作符的二进制位都不同所以异或后都为原来3的二进制位,3^0=3

            1^2^3与3^2^1最终计算结果是相同的

在此之后我们再来理解以上代码

在b=a^b中的a=a^b,在最后的a=a^b中a=a^b b=a

运行程序验证以上运算

       

练习2

编写代码实现:求⼀个整数存储在内存中的二进制中1的个数 

我们知道要将一个数从十进制转换为二进制是需要通过不断整除2然后取出余数

所以我们可以想到以下方法来求一个数二进制中1的个数

#include
int Number(int n)
{
 int count=0;
 while(a)
 {
  if(a%2==1)
  {
   count++;
  }
  a=a/2;
 }
 return count;
}
int main()
{
 int a=0;
 scanf("%d",&a);
 int n=Number(a);  
 printf("%d",n);
 return 0;
}

在以上方法会存在一个问题就是无法计算负数的二进制1的个数 这时有的读者会想到将形参用unsigned int,这种方法确实能解决问题 但有没有更好的方法呢?

#include
int Number(int a)
{
 int count=0;
 int i=0;
 for(i=0;i>i)&1)
  {
   count++; 
  }
 }
 return count;
}
int main()
{
 int a=0;
 scanf("%d",&a);
 int n=Number(a);  
 printf("%d",n);
 return 0;
}

 以上这种方法是将整数的二进制数的每一位都按位与1,若输出为1就count++;实现二进制位中1的计数 但这种方法也有一定的缺陷就是无论输入整数的二进制位中有几个1都需要将32位全部遍历一遍,这样会使得代码的效率不高 因此我们能否再设计一种方法来让统计出所有二进制1时就停止循环呢?

#include
int Number(int a)
{
 int count=0;
 int i=0;
 while(n)
  {
   a=a&(a-1);
   count++; 
  }
 return count;
}
int main()
{
 int a=0;
 scanf("%d",&a);
 int n=Number(a);  
 printf("%d",n);
 return 0;
}

 要理解上面这种方法首先要了解n&(n-1)结果的特点

n&(n-1)能将整数的二进制位中去除一个1

例如当n=5时

所以利用这种方法就可以在二进制位1的个数为0时不再继续执行程序,提升了程序的效率

练习3

二进制位置0或者置1

 编写代码将13二进制序列的第5位修改为1,然后再改回0

13的2进制序列: 00000000000000000000000000001101

将第5位置为1后:00000000000000000000000000011101

将第5位再置为0:00000000000000000000000000001101

#include
int main()
{
 int a=13;
 printf("%d",a);
  a=a|(1
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon