第十一章位运算一、位运算的概念二、位运算符三、位运算的常用用法四、位运算复合赋值运算符五、位段前面所学习的所有运算都是对某个变量所进行的操作,其实C语言还可以对变量中的个别位进行操作。尤其是使用C语言编写设备驱动程序、嵌入式程序的时候,某个变量的每一位都会有特定的含义。本章将介绍C语言中的位运算。一、位运算的概念日常生活中常用十进制的数据描述事物。但是,对计算机的硬件来说,一个物理器件一般有两个明显的稳定状态,例如:电路的开、关状态;电平的高、低状态;磁盘上某个点的顺磁、逆磁状态;光盘上某个点的平、凹状态等。所以,计算机世界是一个二进制的0、1世界,每个0或1是一个位。8个位组成一个字节。在VC编译系统中,一个int型变量占4个字节,也就是32位的存储单元。位运算可以对32个位中的任意一位进行运算。例如:inta;a=4;如图所示。二、位运算符在C语言中,提供位逻辑运算符和移位运算符。1、位逻辑运算符C语言中位逻辑运算符有四种:按位与、按位或、按位异或、按位取反。1)“按位与”运算符——“&”参加运算的两个数据,按二进位进行“与”运算。运算规则是:0&0=0;0&1=0;1&0=0;1&1=1;【例11-1】3&5值是多少?#includevoidmain(){printf("%d\n",3&5);}【例11-2】-3&-5值是多少?#includevoidmain(){printf("%d\n",-3&-5);}2)“按位或”运算符——“|”两个相应的二进位中只要有一个为1,该位的结果值为1。运算规则是:0|0=0;0|1=1;1|0=1;1|1=1;【例11-3】060|017的值是多少?(八进制)#includevoidmain(){printf("%o\n",060|017);}3)“按位异或”运算符——“∧”参加运算的两个二进位同号,则结果为0(假);异号则为1(真)。运算规则是:00=0;01=1;10=1;11=0;∧∧∧∧【例11-4】0x390x2a∧的值是多少?(十六进制)#includevoidmain(){printf("%x\n",0x39^0x2a);}4)“按位取反”运算符——“~”“~”是一个单目运算符,用来对一个二进制数按位取反,即将0变1,1变0。【例11-5】~025的值是多少?(八进制)#includevoidmain(){printf("%o\n",~025);}2、移位运算符1)“左移”运算符——“<<”用来将一个数的各二进位全部左移若干位,右补0。【例11-6】若a=15;a=a<<2;则a的值是多少?#includevoidmain(){inta=15;a=a<<2;printf("%d\n",a);}说明:1)高位左移后溢出,舍弃不起作用。2)左移1位相当于该数乘以21,左移2位相当于该数乘以22,即左移n位相当于该数乘以2n。此结论只适用于该数左移时被溢出舍弃的高位中不包含1的情况。例如:假设以一个字节(8位)存一个整数,若a为无符号整型变量,则a=64;时,左移一位时溢出的是“0”,相当于乘以21,值为128;而左移2位时,溢出的高位是“01”,值为0。如图所示。3)左移比乘法运算快得多,有些C编译系统自动将乘2的运算用左移一位来实现,将乘2n的幂运算处理为左移n位。2)“右移”运算符——“>>”移到右端的低位被舍弃。【例11-7】若a=017;a=a>>2;则a的值是多少?#includevoidmain(){inta=017;a=a>>2;printf("%o\n",a);}说明:1)右移1位相当于除以21,右移2位相当于除以22,右移n位相当于除以2n。2)在右移时,需要注意符号位问题。对无符号数,右移时左边高位移入0。对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0。如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统:有的系统移入0,有的移入1。(移入0的称为“逻辑右移”,即简单右移;移入1的称为“算术右移”)3)在VC编译系统中,采用的是“算术右移”,即对有符号数右移时,如果符号位原来为1,左面移入高位的是1。【例11-8】若a=0xfffffffe;a=a>>1;则a的值是多少?#includevoidmain(){inta=0xfffffffe;a=a>>1;printf("%d\n",a);}三、位运算的常用用法1、置位0将某些位设置为0。在控制某些设备时,用于关闭某个装置,比如关闭显卡的输入。使用“按位与”运算,在需要置为0的位上与“0”进行“按位与”,保持不变的位与“1”进行“按位与”。例如:将8位二进制数01001011的最低位置为0,其它位不变,如...