juliusun.com
第 49/50 节 冥河C语言教程
内存中的数据都是以二进制的形式存放的,二进制只有0和1。一个0或1表示一位,英文名为bit。8位组成1个字节,英文名byte。位运算就是对每一位的二进制0或1进行运算。
本节我们需要介绍的运算符如下:
符号 | 名称 |
---|---|
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~ | 取反 |
<< | 左移 |
>> | 右移 |
注意区分一下,两个取地址符&&是逻辑运算符并,一个取地址运算符&是位运算按位与。两个竖线是逻辑运算符或,一个竖线是位运算按位或。
位运算两个数组数大小不一致时,对于无符号类型,将占用内存小的数字高位补0,达到相同位数再运算。对于有符号类型,将占用内存小的数字高位补符号位(即正数补0负数补1)再运算。
按位与& 作用是将两个数字相对应的位进行与运算,与运算的结果是,两个二进制位,均为1,结果才为1,否则为0。按位与运算规则如下:
表达式 | 结果 |
---|---|
0 & 0 | 0 |
0 & 1 | 0 |
1 & 0 | 0 |
1 & 1 | 1 |
本段无特殊说明,进制均是二进制,如 1010 & 0011 = 0010。最高位为第1位,最低位为第4位。则第一位为1&0=0,第二位0&0=0,第三位1&1=1,第四位0&1=0。组合一下第1到第4位结果为0010。1010、0011、0010换算成10进制分别为10、3、2,换算成16进制分别为a、3、2。
代码用unsigned char类型说明,char占8位,方便起见,高4位为0不考虑:
标准C语言没有以二进制输出数字的格式,有点不方便,不过节后面会给出一个将数字转换成二进制并输出的例子。
按位或| 作用是将两个数字对应的二进制位进行或运算,两边的二进制至少有一方为1结果即为1。换个说法就是两边的二进制均为0,结果才为0,否则为1。按位或规则如下:
表达式 | 结果 |
---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
本段无特殊说明,进制均是二进制,如 1010 | 0011 = 1011。最高位为第1位,最低位为第4位。则第一位为1 | 0= 1,第二位0 | 0=0,第三位1 | 1=1,第四位0 | 1=1。组合一下第1到第4位结果为1011。1010、0011、1011换算成10进制分别为10、3、11,换算成16进制分别为a、3、b。
按位异或^ 作用是将两个数字对应的二进制位进行比较,相同为0,不同为1。按位异或规则如下:
表达式 | 结果 |
---|---|
0 ^ 0 | 0 |
0 ^ 1 | 1 |
1 ^ 0 | 1 |
1 ^ 1 | 0 |
本段无特殊说明,进制均是二进制,如 1010 ^ 0011 = 1001。最高位为第1位,最低位为第4位。则第一位为1 ^ 0= 1,第二位0 ^ 0=0,第三位1 ^ 1=0,第四位0 ^ 1=1。组合一下第1到第4位结果为1011。1010、0011、1011换算成10进制分别为10、3、9,换算成16进制分别为a、3、9。
以上例子注意,unsigned char a=0xa,由于a占用8位,补全应该是二进制0000 1010。由于以上例子高4位均为0,且0和0做与、或、异或运算仍然是0,因为排序了高位干扰,注意下unsigned char是占用8个二进制位的。
取反~ 一元运算符,后面接表达式。作用是如果二进制位为0,则结果为1;如果二进制位为1,则结果为0。取反规则如下:
表达式 | 结果 |
---|---|
~0 | 1 |
~1 | 0 |
本段无特殊说明,进制均是二进制,如 ~11111 1001 = 0000 0110。方便查看,高4位与低四位之间加了空格。1111 1001、0000 0110换算成10进制分别为249、6,换算成16进制分别为f9、6。
左移运算符<< 用法为"数字O<<数字N"。使用的是将"数字O"二进制每位向高位(即左边)移动"数字N"位,右边补0,左边移出的部分省略。方便说明,没有字母前缀的为10进制数字,带有大写字母B前缀的为二进制数字,则B 0000 1111<<2 = B 0011 1100,另外一例:B1011 1111<<1 = B0111 1110,未左移前的最高位1被移出,舍弃不用。移动后最右边的0为自动补充。
例二进制1111 1001左移两位:
当左移N位时,如果左边舍弃的位无1,且是无符号或左移后最高位仍为0,起到的作用的乘以2的N次方。
右移运算符>> 用法为"数字O>>数字N"。使用的是将"数字O"二进制每位向低位(即右边)移动"数字N"位,右边移出的部分舍弃不用。左边填充时稍显复杂,无符号类型左右直接补0;有符号时,正数(即最高位为0)时左边补0,负数(即最高位为1)时左边补1或0依赖运行时的计算机系统。
左边填充规则总结一下,右移时,"数字O"为无符号类型或正数的有符号类型,左边补0,"数字O"为有符号且为负数时,左边补1或0依赖运行时的计算机系统。
本节只讨论无符号的情况,以下例子均以无符号数字右移为例。方便说明,没有字母前缀的为10进制数字,带有大写字母B前缀的为二进制数字,则B 0000 1111>>2 = B 0000 0011,另外一例:B1011 1111>>1 = B0101 1111。
例二进制0011 1001右移两位:
下面用位运算实现输出一个unsigned char类型的二进制:
效果类似如下图:
效果图供供参考,不同平台有所差异。