关于位运算
位运算是对值的各个位进行操作,在前面的博客里关于原码、反码、补码的取值方式等都是对各个数据的位进行操作,C和C++中共有6种位运算符,分为两类:(1)移位运算符(2)逻辑按位运算符,在这里简单整理一下关于位运算的知识。
一、移位运算符
移位运算符分两个,左移运算符和右移运算符:
左移运算符:<<
左移运算符的语法为:val<<shift:其中val是要被操作的数值,shift是要移动的位数。这里以13为例。
例如对13进行左移3位,因为位运算符都是对数据的位进行操作,所以我们需要先将13转为二进制表示如下:
注意此时:
1.超出边界的位将被丢弃,前面的3个0都被丢弃;
2.空出来的位补0;
可以看到此时的数字变为了0110 1000,转换为十进制为104,由算术运算可得13*2^3=104,所以左移运算符中左移几位代表将当前数字乘以2的几次方。
左移运算符在汇编语言中是会直接修改当前值的值,以新值代替旧值,而C++中则会产生一个新的量来保存这个移位后的值的,可以做个小测试:
不过位运算符合其他运算符相同,也支持“<<=”这种运算,可以直接改变其值:
右移运算符:>>
右移运算符和左移运算符相同,也是移动bit位,只不过是向右移动:
右移对多余位的处理方式和左移是一样的,直接丢弃;但对空出来的位来说,则有以下两种方案:
1.无符号数直接补0;
2.有符号的数字则视其符号位,若符号位为0则补入0,符号位为1则补入1,这样做是为了保证数字的符号不变。
类似的,右移操作也是对该数字进行2的幂次方操作,右移为除法运算。
对其做个测试:
同样,右移运算符也支持“>>=”这种运算。因为在有些系统上对数字做移位运算比做乘除运算快,所以对效率有一定的影响,可以试着运用一下。
二、逻辑按位运算符
逻辑按位运算符是对数字的每一个bit位进行操作:
按位取反(NOT):~
对于无符号整数,取反运算符将数值的每一位都取成对应位上的相反数,0取成1,1取成0,我们依旧以13为例,因为占用字节数太多的也没有什么研究意义,就用占用两个字节的无符号短整型来定义13:
我们也对其做一个小测试:
而当输入的数字为有符号数时则会因为取反而导致的符号位改变,而且取决于数字的存储字节数,所以可能会导致越界,进一步使输出的数字和臆想的不同,这点可以自己做些实验。
按位或(OR):|
按位或需要对两个数字进行操作,将两个数字的相应bit位进行比对,对应位上只要有1,得到的结果中对应的位也为1,使用13和17进行实验,先将他们转换为二进制数:
同样我们在计算机上测试一下:
按位异或(XOR):^
按位异或和按位或有相似之处,但按位异或是当两个数字中不同时新值对应位为1,否则为0。同样我们以13和17作为测试用例:
在编译器上执行:
按位与(AND):&
按位与运算符将两个二进制数中都为1的位设为1,其余均为0,对13和17则如下:
在编译器上测试:
逻辑与可以和简洁与对照理解,其实这些逻辑运算符都可以对应着看,只不过是操作的对象变成了位上的数字,在编程中我们对位的应用还是挺多的,所以这几个运算符搞清楚还是挺有必要。