12.1位运算C语言具有位逻辑运算和移位运算的独特功能,参与位运算的运算量必须是整数。位逻辑运算包括&、|、∧、~四种运算,移位运算有、两种运算。其中~位单目运算符。12.1.1按位与12.1.2按位或12.1.3按位异或12.1.4按位取反12.1.5按位左移12.1.6按位右移12.1.7位运算的复合赋值运算符12.1.1按位与参与运算的量,如果相对应的两位都为1,则该位的结果值为1,否则为0,即:0&0==00&1==01&0==01&1==1如:a的值为0x1234,b的值为0x00,a&b运算的结果c应为:a0001001000110100&b0000000011111111c0000000000110100按位与常用于将某个运算量的某些位清0或提取某些位的值,如本例中,将变量的高8位清0,同时保留或提取低8位的值,可用一个高8位为0,低8位为1的值0x00ff和它进行按位与。12.1.2按位或参与运算的量,如果相对应的两位都为0,则该位的结果值为0,否则为1,即:0|0==00|1==11|0==11|1==1如:a的值为0x1234,b的值为0x00,a|b运算的结果c应为:a0001001000110100|b0000000011111111c0001001011111111按位或常用于将某个运算量的某些位置1,如本例中将变量的低8位置1,高8位不变,可用一个高8位为0,低8位为1的值0x00ff和它进行按位或。12.1.3按位异或参与运算的量,如果相对应的两位相异,则该位的结果为1,否则为0,即:0∧0==00∧1==11∧0==11∧1==0如:a的值为0x1234,b的值为0x00,a∧b运算的结果c应为:a0001001000110100∧b0000000011111111c0001001011001011按位异或有“与1异或”该位翻转,“与0异或”该位不变的规律。如本例中用0x00ff进行按位异或,使变量a的低8位翻转,高8位不变。12.1.4按位取反将参与运算量的相对应位的值取反,即1变0,0变1。如:a的值为0x1234,~a运算的结果c应为:~a0001001000110100c111011011100101112.1.5按位左移按位左移是将一个运算量的各位依次左移若干位,低位补0,高位舍弃不要。假设机器字长为8位,变量a的值为16,将a左移二位,即a=a2:左移前00010000左移后01000000由此看出,左移一位相当于该数乘2,左移二位相当于乘4,即22,但这要以该数左移之后不“溢出”为前提。所谓“溢出”指该数已超过机器字长所能容纳的范围,如该例若继续左移二位,该数为16×24=256,超出了字长8位的表示范围(257),即产生了溢出。12.1.6按位右移按位右移是将一个运算量的各位依次右移若干位,低位被移出,高位对无符号数补0,对有符号数要按最高符号位自身填补。右移一位相当于该数除以2,但有可能带来误差。假设机器字长为8位,变量a值为15,将a右移二位,即a=a2:右移前00001111右移后00000011如果a是带符号的负数,a=-16,存放在机器中的补码为11110000,则a=a2,值为-4。右移前11110000右移后11111100表12.3位运算符的运算规则把操作数右移指定的位数右移把操作数左移指定的位数左移把操作数各位0变1,1变0取反~两个相应位相同为0,其余为1位异或∧两个相应位全0为0,其余为1位或|两个相应位全1为1,其余为0位与&运算规则名称运算符12.1.7位运算的复合赋值运算符共有五种位运算的复合赋值运算符:&=(位与赋值)、|=(位或赋值)、∧=(位异或赋值)、=(按位右移赋值)、=(按位左移赋值)。例如:a∧=b相当于a=a∧ba=3相当于a=a312.2位段的概念所谓位段,相当于结构体类型中的成员,但是定义位段的长度是以位为单位。它是一种特殊的结构体类型。(1)位段的定义定义位段的一般形式为:struct结构体类型标识符{unsigned位段名1:长度1;unsigned位段名2:长度2;……….unsigned位段名n:长度n;}变量名表;(2)说明:1.在定义中,每个位段(相当于成员)的长度是以位为单位,因此位段的类型为unsigned。2.一个位段必须存储在同一存储单元,不能跨两个单元。即一个位段的长度不能大于一个单元存放。3.当某个位段开始存放时,若相应的存储单元空间不够,则剩余空间不用,该位段将在下一个单元存放。例如,设某个系统存储单元长度为8(一个字节),且有如下的定义:struct{unsigneda:4;unsignedb:2;unsignedc:6;}x;abc4.可以定义无名位段。例如:struct{unsigneda:4;unsigned:3;unsignedb:2;unsignedc:6;}x;此位段无名,该3位闲置不用。5.可以用长度为0的无名位段,使下一个位段从另一个存储单元开始存放。struct{unsignedaa:4;unsigned:3;unsignedbb:2;unsigned:0;unsignedcc:6;}y;6.注意,不能定义位段数组。(3)位段的引用:•可以用赋值语句赋值例:x.a=4;y.cc=6;•可以在表达式中引用,C语言将自动将其转换为int类型例:x.a++;y.cc=y.aa+1;•可以用整型格式输出例:printf(“a=%db=%dc=%d”,x.a,x.b,x.c);变量名.位段名