最开始提到C语言操作符,我还是有一些不屑的,这玩意有啥学的呀?今天静下心来阅读学习了一下操作符部分的知识,这部分还真得认真学习学习!下面我将操作符中一些比较关键的点进行罗列和详细说明。一来帮助我加深理解,二来希望能帮助到有缘点击进来的读者。
1、算术操作符:+ - * / %
上面的五种操作符需要提一嘴的就只有除(/)和取余(%)操作符了。这几种操作符除了取余(%)操作符外,其他操作符均可以作用于整数和浮点数,取余操作符的两个操作数必须为整数。而对于(/)操作符,如果两个操作数都是整数,则进行整数除法。而只要是有浮点数执行的就是浮点数整除法。
2、移位操作符:<< >>
<< : 左移操作符,移位规则:左边抛弃,右边补零。
>> : 右移操作符,移位规则分为两种:
1、逻辑移位:左边补零,右边抛弃;
2、算术移位:左边使用原该值的符号位进行填补,右边抛弃;
3、位操作符:& | ^
& :按位与操作符
| :按位或操作符
^ : 按位异或操作符 (位操作符的操作数均为整数)
***这有啥讲的呀??来一道题显示它们的真功夫。
题目1:输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
有人想到,我们可以类比取出十进制数字的方法进行求解,是的,我么可以来试一试。思路大概是这样的:
代码实现:
#include <stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
while (num)
{
if (num % 2 == 1)
count++;
num = num / 2;
}
printf("%d\n", count);
return 0;
}
上面的代码在表面上是可以检查的,当你的输入变成负数之后,例如-1时,程序的输出结果为:
上述的结果显然与事实不符,-1在内存中的形式为补码形式:11111111 11111111 11111111 11111111;也就是32个1,所以显然上述程序的输出结果是错误的。
所以下面有请我们的主角登场,按位与(&)
我们当然知道他的运算逻辑,当两个数中有0,结果就为0,两者都为1,结果就为1;
所以也就有了下面的思路:
按照上面的思路,我们将整个整型的每一个比特位进行按位右移并且与数字1按位与,通过检测按位与的结果是否为1,来实现统计原数中1的个数。
解法1:
#include <stdio.h>
int NumberOf1(int n) {
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n>>i)&1) == 1)
count++;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret =NumberOf1(num);
printf("%d\n", ret);
return 0;
}
让我们来测试一下:
结果是正确的。
解法2:
按照上面的逻辑,可以写出一下程序:
#include <stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
while (num)
{
num = num & (num - 1);//每次计算会消除最右侧的1
count++;
}
printf("%d\n", count);
return 0;
}
我们再次使用-1来进行验证算法的正确性,当然也普适于其他数据。
上述算法提供了一个全新的思路。
题目2:不创建临时变量,实现两个数字的交换。
两个数交换最常规的思路是创建临时变量,上述题目中要求不使用临时变量,这里可以使用按位异或来进行解决。这里我们需要知道异或的性质。
简单来说:就是一个数和它自己异或操作的结果为0;0与任意数异或的结果位任意数本身。
借助这个性质,我们便可以做到不使用中间临时变量进行两个数据的交换。
#include <stdio.h>
int main()
{
int a = 2;
int b = 3;
printf("交换前:a=%d,b=%d\n",a,b);
a = a ^ b; //先将两个数的异或结果进行存放
b = a ^ b; //a^b^b的结果为a,将a放在b中 b的值为a
a = a ^ b; //a^b^a (b=a) 的结果为b,将b放在a中
printf("交换后:a=%d,b=%d\n", a, b);
return 0;
}
标签:count,int,C语言,异或,num,按位,操作符
From: https://blog.csdn.net/qq_70199082/article/details/143058359