今天主要学习一下位操作符。
今天也要心情愉悦的学习呀!
1.都有哪些操作符?怎么用呢?
& 按位与:逐比特位运算 同1为1,其他为0
| 按位或 : 逐比特位运算 同0为0,其他为1
^ 按位异或 :逐比特位运算 相异为1,相同为0
~ 取反 :逐比特位运算 按位取反(单目操作符)
<< 左移 :逐比特位左移最低位补0
>>右移:逐比特位右移有符号补最高位补符号位,无符号数补0。
除了~取反,其他都是双目操作符。
2.位操作符适用于哪些数据类型呢?
答案是只适用于整形家族,不适合浮点型家族。
本质原因是因为两者的数据存储类型不同。
整形家族的存储在上篇说过了,不在赘述。
- 整形家族存储方式
浮点型家族的存储方式,要符合IE754的规定。
3.按位与 按位或 按位异或 的实例
例 1: 求二进制中1的个数。 采用&(按位与)
int a = 0;
scanf("%d", &a);
int count = 0;
while (a)
{
a = a&(a - 1);//每次把最低位丢弃,直到a为0.
count++;
}
printf("%d\n", count);
例 2:求二进制中0的个数 采用 | (按位或),(很有趣,可以看看)
int a = 0;
int count = 0;
scanf("%d", &a);
while (a+1)
{
a = a | (a + 1);
count++;
}
printf("%d\n", count);
这个代码很有趣,是采用数据溢出后截断来使判断条件成立的。
首先,判断处采用a+1是因为要使0也要进去,更巧的是,当a+1等于0的时候,刚好a是 -1,我们知道-1的二进制补码中是没有0的,所以刚好符合,这是采用的每次使一个比特位的变成1,到最后使数据变为负数(-1),再加1变为0,终止循环。
例 3: 采用 ^ (按位异或)交换两个变量的值。
首先要知道一些最基本的结论:
1 .一个数异或0,还是它本身。
2.一个数异或它本身为0
这是根据异或概念得出的。
下面再看这题,是不是有点思路了。
先a异或b,然后再进行一次异或,相当于b = b^ b^a.
同理可得出a。
int a = 10;
int b = 20;
printf("before:%d %d\n", a, b);
a = a^b;
b = a^b;
a = a^b;
printf("after:%d %d\n", a, b);
下面是数学法。
int a = 10;
int b = 20;
printf("before:%d %d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("after:%d %d\n", a, b);
异或法比数学法最大的好处就是不用考虑溢出的问题,如果两个非常大的数进行数学法运算可能会溢出。
4.左移 右移操作符
左移比较简单,丢弃高位,低位补0。
右移分情况讨论了 :
算数右移 :有符号的数来说,最高位补符号位。
逻辑右移:无符号的数来说,最高位补0。
看个例子 :
int a = -1;
unsigned int b = -1;
printf("%d\n", a >> 1);
printf("%u\n", b >> 1);
运行后发现,先打印的是-1,然后是打印的是230-1.
先分析a>>1,因为a是有符号的负数,所以补位时最高位符号位1,最后的补码值还是全1.
再看b>>1,因为b是无符号数,所以补位时最高位补0,最后是出来第一个比特位是0,其他都为1。
那么移位的范围是什么呢?
首先int型的数据只有32位,所以移位最大是31位,那么最小值呢?是最小值是**-31位吗?**不是的,左移还有右移都不能移位负数位。
所以移位的范围是0~31位。
看个例子
比较下优先级的问题。
int a = 1;
a = a << 2 + 3;
printf("%d", a);
首先,结果是32,那么这样看的话,是先进行(2+3),在进行移位。
所以使用移位符时,要考略优先级的问题。
5.移位符应用
使用移位符可以逐比特位置为0或1.
逐比特位,置1.
unsigned int a = 1;
int i = 0;
for (i = 0; i < 32; i++)
{
a = a|(a << i);
}
printf("%d", a);
因为最后是有符号数,所以打印为-1。
逐比特位,置0
unsigned int a = -1;
for (int i = 0; i < 32; i++)
{
a = a & (a >> i);
}
printf("%d", a);
因为a为无符号数,所以补位时,补0,进行移位后在进行按位或。最后打印是0。
6. 一些技巧
- x&1 == 0判断是否偶数,偶数的最后一位比特位都是0.
- 两个数的值可以通过异或交换。
- x & (x-1)可以使最右边的比特位上的1变为0.
- 对于正数而言,x&(x-1)== 0就是判断是不是2的幂次方。
- 两个相同的数异或,结果是0,一个数和0异或,结果是他本身。 可以用来找数。
7.下期预告
这期还是没把 ++的东西写完。下期一定讲++和–相关的知识。
下期更精彩~~~