前言:
前篇我们学习过C语言的位与移位操作符详解【C语言】位与移位操作符详解-CSDN博客
这篇博客将带领大家继续练习相关知识。
1.一道变态的面试题
不允许创建临时变量,交换两个整数的内容。
解析:通过上节我们学习的位与移位操作符,我们可以大概知道需要用到它们。
通过学习我们可知:
①a & a = a ②a | a = a ③a ^ a = 0 ④a & 0 = 0 ⑤a | 0 = a ⑥a ^ 0 = a①a & a = a ②a | a = a ③a ^ a = 0 ④a & 0 = 0 ⑤a | 0 = a ⑥a ^ 0 = a
要交换两个整数的内容我们要使用③⑥两个公式
a^a^b=b
代码如下:
#define _CRT_SECURE_NO_WARNINGS 1 //不允许创建临时变量,交换两个整数的内容 #include<stdio.h> int main() { int a = 3; int b = 5; a = a ^ b; b = a ^ b;//实际上是a^b^b=a^0=a a = a ^ b;//实际上是a^b^a=0^b=b printf("%d\n", a); printf("%d\n", b); return 0; }
运行结果如下:
2.输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
方法一:
解析:我们知道按位与是同真为真也就是二进制中都是1才为1,只要有一个不为1就是0;
所以如果我们将n按位与1(1的二进制除了最后一位其他都是0),那么我们就可以知道n最后一位是1还是0了,如果再通过右移操作符将n的二进制一回移动一个,那么我们就可以得知n每位是1还是0了,问题就得到解决啦~
🎉🎉✨检测num中某一位是0还是1的方式:
1.将num向右移动i位
2.将移完位之后的结果与1按位与,如果.结果是0,则第i个比特位是0,结果是非0,则第i个比特位是1
以下是解析图:
代码如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> //2.输入一个整数 n ,输出该数32位二进制表示中1的个数。 // 其中负数用补码表示。 int main() { int n = 0; printf("请输入整数n:"); scanf("%d", &n); int i = 0;//创建i变量用以循环32次 int count = 0;//创建count变量用以记录i的个数 for (i = 0; i < 32; i++) { count += (n>>i) & 1; } printf("\n%d的二进制中1的个数为:%d\n",n,count); return 0; }
运行结果如下:
方法一
优点:用位操作代替取模和除法运算,效率稍微比较高
缺陷:不论是什么数据,循环都要执行32次
方法二:
代码如下:
int main() { int n = 0; printf("请输入整数n:"); scanf("%d", &n); int count = 0;//创建变量计数 while (n & (n - 1))//当n与相邻位按位与不为0时 { n = n & (n - 1); count++; } count += 1;//注意最后为0的也要算进去 printf("\n二进制中1的个数为:%d\n", count); return 0; }
这里要注意两点💥:
(1)n&(n-1)后要将它的值赋给n,而不是将n-1赋给n;
n = n & (n - 1);
(2)最后n&(n-1) = 0时while已经出了循环,所以最后count还要+1;
count += 1;//注意最后为0的也要算进去
代码运行结果如下:
方法三:
代码如下:
int main() { int n = 0; printf("请输入整数n:"); scanf("%d", &n); int count = 0;//创建变量计数 while (n) { if (n % 2 == 1) count++; n =n/ 2; } printf("\n二进制中1的个数为:%d\n", count); }
运行结果如下:
上述方法缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。
3.打印整数二进制的奇数位和偶数位
思路:
1.提取所有的奇数位,如果该位是1,输出1,是0则输出0
2.以同样的方式提取偶数位置(我们可以用移位操作符来提取)
💫检测num中某一位是0还是1的方式:
1.将num向右移动i位
2.将移完位之后的结果与1按位与,如果.结果是0,则第i个比特位是0,结果是非0,则第i个比特位是1
代码如下:
int main() { int num = 0; printf("请输入整数num:"); scanf("%d", &num); for (int i = 31; i >= 1; i -= 2) { printf("%d ", (num >> i) & 1); } printf("\n"); for (int i = 30; i >= 0; i -= 2) { printf("%d ", (num >> i) & 1); } printf("\n"); return 0; }
运行结果如下: