第12章位运算 为了节省内存空间,在系统软件中常将多个 标志状态简单地组合在一起,存储到一个字节 (或字)中。C语言是为研制系统软件而设计的, 所以她提供了实现将标志状态从标志字节中分离 出来的位运算功能。 所谓位运算是指,按二进制位进行的运算。 12.1数值在计算机中的表示 2.2位运算 123位段
第12章 位运算 为了节省内存空间,在系统软件中常将多个 标志状态简单地组合在一起,存储到一个字节 (或字)中。C语言是为研制系统软件而设计的, 所以她提供了实现将标志状态从标志字节中分离 出来的位运算功能。 所谓位运算是指,按二进制位进行的运算。 12.1 数值在计算机中的表示 12.2 位运算 12.3 位段
121数值在计算机中的表示 1二进制位与字节 计算机系统的内存储器,是由许多称为字节的单元组 成的,1个字节由8个二进制位(bit)构成,每位的取值为 0/1。最右端的那1位称为“最低位”,编号为0;最左端的 那1位称为“最高位”,而且从最低位到最高位顺序,依次 编号。图11-1是1个字节各二进制位的编号 76543210 图12-11个字节各二进制位的编号 2数值的原码表示 数值的原码表示是指,将最高位用作符号位(0表示正 数,1表示负数),其余各位代表数值本身的绝对值(以 进制形式表示)的表示形式。为简化描述起见,本节约定 用1个字节表示1个整数
12.1 数值在计算机中的表示 1.二进制位与字节 计算机系统的内存储器,是由许多称为字节的单元组 成的,1个字节由8个二进制位(bit)构成,每位的取值为 0/1。最右端的那1位称为“最低位”,编号为0;最左端的 那1位称为“最高位”,而且从最低位到最高位顺序,依次 编号。图11-1是1个字节各二进制位的编号。 图12-1 1个字节各二进制位的编号 2.数值的原码表示 数值的原码表示是指,将最高位用作符号位(0表示正 数,1表示负数),其余各位代表数值本身的绝对值(以二 进制形式表示)的表示形式。为简化描述起见,本节约定 用1个字节表示1个整数。 7 6 5 4 3 2 1 0
例如,+9的原码是00001001 L符号位上的0表示正数 9的原码是10001001。 L→符号位上的1表示负数 3数值的反码表示 数值的反码表示分两种情况: (1)正数的反码:与原码相同 例如,+9的反码是00001001 (2)负数的反码:符号位为1,其余各位为该数绝 对值的原码按位取反(1变0、0变1) 例如,-9的反码:因为是负数,则符号位为“1”; 其余7位为9的绝对值+9的原码0001001按位取反为 1110110,所以9的反码是11110110
例如,+9的原码是00001001 └→符号位上的0表示正数 -9的原码是10001001。 └→符号位上的1表示负数 3.数值的反码表示 数值的反码表示分两种情况: (1)正数的反码:与原码相同。 例如,+9的反码是00001001。 (2)负数的反码:符号位为1,其余各位为该数绝 对值的原码按位取反(1变0、0变1)。 例如,-9的反码:因为是负数,则符号位为“1” ; 其余7位为-9的绝对值+9的原码0001001 按位取反为 1110110,所以-9的反码是11110110
4数值的补码表示 数值的补码表示也分两种情况 (1)正数的补码:与原码相同 例如,+9的补码是00001001 (2)负数的补码:符号位为1,其余位为该数绝对值 的原码按位取反;然后整个数加1 例如,9的补码:因为是负数,则符号位为“1;其 余7位为-9的绝对值+9的原码0001001按位取反为1110110 再加1,所以9的补码是111111 已知一个数的补码,求原码的操作分两种情况 (1)如果补码的符号位为“0,表示是一个正数,所 以补码就是该数的原码 2)如果补码的符号位为“1”,表示是一个负数,求 原码的操作可以是:符号位不变,其余各位取反,然后再 整个数加1
4.数值的补码表示 数值的补码表示也分两种情况: (1)正数的补码:与原码相同。 例如,+9的补码是00001001。 (2)负数的补码:符号位为1,其余位为该数绝对值 的原码按位取反;然后整个数加1。 例如,-9的补码:因为是负数,则符号位为“1”;其 余7位为-9的绝对值+9的原码0001001按位取反为1110110; 再加1,所以-9的补码是11110111。 已知一个数的补码,求原码的操作分两种情况: (1)如果补码的符号位为“0” ,表示是一个正数,所 以补码就是该数的原码。 (2)如果补码的符号位为“1” ,表示是一个负数,求 原码的操作可以是:符号位不变,其余各位取反,然后再 整个数加1
例如,已知一个补码为11101,则原码是 10000111(-7):因为符号位为“1,表示是一 个负数,所以该位不变,仍为“1;其余7位 111101取反后为0000110;再加1,所以是 1000011l。 5数值在计算机中的表示补码 在计算机系统中,数值一律用补码表示(存 储),原因在于:使用补码,可以将符号位和其 它位统一处理;同时,减法也可按加法来处理 另外,两个用补码表示的数相加时,如果最高位 (符号位)有进位,则进位被舍弃
例如,已知一个补码为11111001,则原码是 10000111(-7):因为符号位为“1” ,表示是一 个负数,所以该位不变,仍为“1”;其余7位 1111001 取反后为 0000110 ; 再 加 1 , 所以是 10000111。 5.数值在计算机中的表示──补码 在计算机系统中,数值一律用补码表示(存 储),原因在于:使用补码,可以将符号位和其 它位统一处理;同时,减法也可按加法来处理。 另外,两个用补码表示的数相加时,如果最高位 (符号位)有进位,则进位被舍弃
122位运算 1221位运算及其运算符 1.按位与—& (1)格式:x&y (2)规则:对应位均为1时才为1,否则为0:3&9=1 例如,3&9=1:0011 &1001 (3)主要用途:取(或保留)个数的某(些)位,其余各位置0。 2.按位或一 (1)格式 (2)规则:对应位均为0时才为0,否则为1:39=11 例如,39=11:001 11001 1011=11 (3)主要用途:将1个数的某(些)位置1,其余各位不变
12.2 位 运 算 12.2.1 位运算及其运算符 1.按位与──& (1)格式:x&y (2)规则:对应位均为1时才为1,否则为0:3&9=1。 例如,3&9=1: 0011 & 1001 ──── 0001=1 (3)主要用途:取(或保留)1个数的某(些)位,其余各位置0。 2.按位或──| (1)格式:x|y (2)规则:对应位均为0时才为0,否则为1:3|9=11。 例如,3|9=11: 0011 | 1001 ──── 1011=11 (3)主要用途:将1个数的某(些)位置1,其余各位不变
3.按位异或— (1)格式:xy (2)规则:对应位相同时为0,不同时为1:3^9=10。 (3)主要用途:使1个数的某(些)位翻转(即原来为1的位 变为0,为0的变为1),其余各位不变 4.按位取反 (1)格式:~x (2)规则:各位翻转,即原来为1的位变成0,原来为0的 位变成1:在 IBM-PC机中,~0=0xf,9=0xf6 (3)主要用途:间接地构造一个数,以增强程序的可移 植性。 5.按位左移—<< (1)格式:x<位数 2)规则:使操作数的各位左移,低位补0,高位溢出 5<<2=20
3.按位异或──^ (1)格式:x^y (2)规则:对应位相同时为0,不同时为1:3^9=10。 (3)主要用途:使1个数的某(些)位翻转(即原来为1的位 变为0,为0的变为1),其余各位不变。 4.按位取反──~ (1)格式:~x (2)规则:各位翻转,即原来为1的位变成0,原来为0的 位变成1:在IBM-PC机中,~0=0xffff,~9=0xfff6。 (3)主要用途:间接地构造一个数,以增强程序的可移 植性。 5.按位左移──<< (1)格式:x<< 位数 (2)规则:使操作数的各位左移,低位补0,高位溢出: 5<<2=20
6.按位右移—>> 1)格式:x>>位数 (2)规则:使操作数的各位右移,移出的低位舍弃; 高位: 对无符号数和有符号中的正数,补0; 2)有符号数中的负数,取决于所使用的系统:补0的 称为“逻辑右移”,补1的称为“算术右移”。例如,20 2=5。 说班 (1)ⅹ、y和“位数”等操作数,都只能是整型或字 符型数据。除按位取反为单目运算符外,其余均为双目 运算符。 (2)参与运算时,操作数x和y,都必须首先转换成 二进制形式,然后再执行相应的按位运算 例如,52=5:10100 00101
6.按位右移──>> (1)格式:x>>位数 (2)规则:使操作数的各位右移,移出的低位舍弃; 高位: 1)对无符号数和有符号中的正数,补0; 2)有符号数中的负数,取决于所使用的系统:补0的 称为“逻辑右移” ,补1的称为“算术右移” 。例如,20 >> 2=5。 说明: (1)x、y和“位数”等操作数,都只能是整型或字 符型数据。除按位取反为单目运算符外,其余均为双目 运算符。 (2)参与运算时,操作数x和y,都必须首先转换成 二进制形式,然后再执行相应的按位运算。 例如,5> 2=5:10100 → 00101
3)实现&、^运算主要用途的方法 1)构造1个整数:该数在要取(或保留)的位、或 要置1的位、或要翻转的位上为1,其余均为0。 2)进行按位与、或按位或、或按位异或操作。 4)实现按位取反主要用途的方法 )求~0,间接地构造一个全1的数; 2)按需要进行左移或右移操作,构造岀所需要的数 例如,直接构造一个全1的数,在ⅠBMPC机中为 0xff(2字节),而在VAX-11/780上,却是0 xffffffff(4 字节)。如果用~0来构造,系统可以自动适应。具体应 用,请参见[案例1,1 1222应用举例 [例121]从键盘上输入1个正整数给int变量nm,输出 由8~11位构成的数(从低位、0号开始编号)
(3)实现&、|、 ^运算主要用途的方法 1)构造1个整数:该数在要取(或保留)的位、或 要置1的位、或要翻转的位上为1,其余均为0。 2)进行按位与、或按位或、或按位异或操作。 (4)实现按位取反主要用途的方法 1)求~0,间接地构造一个全1的数; 2)按需要进行左移或右移操作,构造出所需要的数。 例如,直接构造一个全1的数,在IBM-PC机中为 0xffff(2字节),而在VAX-11/780上,却是0xffffffff(4 字节)。如果用~0来构造,系统可以自动适应。具体应 用,请参见[案例11.1]。 12.2.2 应用举例 [例12.1] 从键盘上输入1个正整数给int变量num,输出 由8~11位构成的数(从低位、0号开始编号)
基本思路: (1)使变量nm右移8位,将8~11位移到低4位上。 (2)构造1个低4位为1、其余各位为0的整数 (3)与num进行按位与运算 /*案例代码文件名:AL111.C* *程序功能:输出一个整数中由8~11位构成的数*/ main i int num, mask; printf("Input a integer number: ) scanf(%d", &num) num>>=8: *右移8位,将8~11位移到低4位上* mask=~(~0<<4);/*间接构造1个低4位为1、其余各位为0的整数* printf"result=0x%xn", num mask) 程序演示
基本思路: (1)使变量num右移8位,将8~11位移到低4位上。 (2)构造1个低4位为1、其余各位为0的整数。 (3)与num进行按位与运算。 /*案例代码文件名:AL11_1.C*/ /*程序功能:输出一个整数中由8~11位构成的数*/ main() { int num, mask; printf("Input a integer number: "); scanf("%d",&num); num >>= 8; /*右移8位,将8~11位移到低4位上*/ mask = ~ ( ~0 << 4); /*间接构造1个低4位为1、其余各位为0的整数*/ printf("result=0x%x\n", num & mask); } [程序演示]