《C语言程序设计》第12章位运算解读.docx

上传人:b****5 文档编号:30192011 上传时间:2023-08-07 格式:DOCX 页数:8 大小:18.84KB
下载 相关 举报
《C语言程序设计》第12章位运算解读.docx_第1页
第1页 / 共8页
《C语言程序设计》第12章位运算解读.docx_第2页
第2页 / 共8页
《C语言程序设计》第12章位运算解读.docx_第3页
第3页 / 共8页
《C语言程序设计》第12章位运算解读.docx_第4页
第4页 / 共8页
《C语言程序设计》第12章位运算解读.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

《C语言程序设计》第12章位运算解读.docx

《《C语言程序设计》第12章位运算解读.docx》由会员分享,可在线阅读,更多相关《《C语言程序设计》第12章位运算解读.docx(8页珍藏版)》请在冰豆网上搜索。

《C语言程序设计》第12章位运算解读.docx

《C语言程序设计》第12章位运算解读

第12章位运算

为了节省内存空间,在系统软件中常将多个标志状态简单地组合在一起,存储到一个字节(或字)中。

C语言是为研制系统软件而设计的,所以她提供了实现将标志状态从标志字节中分离出来的位运算功能。

所谓位运算是指,按二进制位进行的运算。

例如,+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的补码是11110111。

已知一个数的补码,求原码的操作分两种情况:

(1)如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。

(2)如果补码的符号位为“1”,表示是一个负数,求原码的操作可以是:

符号位不变,其余各位取反,然后再整个数加1。

例如,已知一个补码为11111001,则原码是10000111(-7):

因为符号位为“1”,表示是一个负数,所以该位不变,仍为“1”;其余7位1111001取反后为0000110;再加1,所以是10000111。

5.数值在计算机中的表示──补码

在计算机系统中,数值一律用补码表示(存储),原因在于:

使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。

另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

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格式:

x^y

(2规则:

对应位相同时为0,不同时为1:

3^9=10。

(3主要用途:

使1个数的某(些位翻转(即原来为1的位变为0,为0的变为1,其余各位不变。

4.按位取反──~

(1格式:

~x

(2规则:

各位翻转,即原来为1的位变成0,原来为0的位变成1:

在PC机中,~0=0xffff,~9=0xfff6。

(3主要用途:

间接地构造一个数,以增强程序的可移植性。

5.按位左移──<<

(1格式:

x<<位数

(2规则:

使操作数的各位左移,低位补0,高位溢出:

5<<2=20。

6.按位右移──>>

(1格式:

x>>位数

(2规则:

使操作数的各位右移,移出的低位舍弃;高位:

1对无符号数和有符号中的正数,补0;

2有符号数中的负数,取决于所使用的系统:

补0的称为“逻辑右移”,补1的称为“算术右移”。

(1)x、y和“位数”等操作数,都只能是整型或字符型数据。

除按位取反为单目运算符外,其余均为双目运算符。

(2)参与运算时,操作数x和y,都必须首先转换成二进制形式,然后再执行相应的按位运算。

例如,5<<2=20:

0101→10100,20>>2=5:

10100→00101。

(3)实现&、|、^运算主要用途的方法

1)构造1个整数:

该数在要取(或保留)的位、或要置1的位、或要翻转的位上为1,其余均为0。

2)进行按位与、或按位或、或按位异或操作。

(4)实现按位取反主要用途的方法

1)求~0,间接地构造一个全1的数;

2)按需要进行左移或右移操作,构造出所需要的数。

11.2.2应用举例

[案例12.1]从键盘上输入1个正整数给int变量num,输出由8~11位构成的数(从低位、0号开始编号)。

基本思路:

(1)使变量num右移8位,将8~11位移到低4位上。

(2)构造1个低4位为1、其余各位为0的整数。

(3)与num进行按位与运算。

/*程序功能:

输出一个整数中由8~11位构成的数*/main(

{intnum,mask;

printf("Inputaintegernumber:

";

scanf("%d",#

num>>=8;/*右移8位,将8~11位移到低4位上*/mask=~(~0<<4;/*间接构造1个低4位为1、其余各位为0的整数*/printf("result=0x%x\n",num&mask;

}[程序演示]

程序运行情况:

Inputaintegernumber:

1000←┘

result=0x3

程序说明:

~(~0<<4

按位取0的反,为全1;左移4位后,其低4位为0,其余各位为1;再按位取反,则其低4位为1,其余各位为0。

这个整数正是我们所需要的。

[案例12.2]从键盘上输入1个正整数给int变量num,按二进制位输出该数。

/*程序功能:

按二进制位输出一个整数*/

#include"stdio.h"

main(

{

intnum,mask,i;

printf("Inputaintegernumber:

";

scanf("%d",#

mask=1<<15;/*构造1个最高位为1、其余各位为0的整数(屏蔽字*/printf("%d=",num;

for(i=1;i<=16;i++

{

putchar(num&mask?

'1':

'0';/*输出最高位的值(1/0*/

num<<=1;/*将次高位移到最高位上*/

if(i%4==0putchar(',';/*四位一组,用逗号分开*/

}

printf("\bB\n";

}[程序演示]

程序运行情况:

Inputaintegernumber:

1000←┘

1000=0000,0011,1110,1000B

12.2.3说明

1.复合赋值运算符

除按位取反运算外,其余5个位运算符均可与赋值运算符一起,构成复合赋值运算符:

&=、|+、^=、<<=、>>=

2.不同长度数据间的位运算──低字节对齐,短数的高字节按最高位补位:

(1)对无符号数和有符号中的正数,补0;

(2)有符号数中的负数,补1。

inti=1;

shorts=-1;

printf("%x\n",i|s;

printf("%x\n",i&s;

12.3位段简介

有时,存储1个信息不必占用整个字节,只需二进制的1个(或多个)位就够用。

如果仍然使用结构类型,则造成内存空间的浪费。

为此,C语言引入了位段类型。

1.位段的概念与定义

所谓位段类型,是一种特殊的结构类型,其所有成员均以二进制位为单位定义长度,并称成员为位段。

例如,CPU的状态寄存器,按位段类型定义如下:

structstatus

{unsignedsign:

1;

/*符号标志*/unsignedzero:

1;

/*零标志*/unsignedcarry:

1;

/*进位标志*/unsignedparity:

1;

/*奇偶/溢出标志*/unsignedhalf_carry:

1;

/*半进位标志*/unsignednegative:

1;

/*减标志*/

}flags;

显然,对CPU的状态寄存器而言,使用位段类型,比使用结构类型节省了多个存储单元。

2.说明

(1)因为位段类型是一种结构类型,所以位段类型和位段变量的定义,以及对位段(即位段类型中的成员)的引用,均与结构类型和结构变量一样。

(2)对位段赋值时,要注意取置范围。

一般地说,长度为n的位段,其取值范围是:

0~(2n-1)。

(3)使用长度为0的无名位段,可使其后续位段从新的存储单元开始存储。

例如,

structstatus

{unsignedsign:

1;

/*符号标志*/unsignedzero:

1;

/*零标志*/unsignedcarry:

1;

/*进位标志*/unsigned:

0;

/*长度为0的无名位段*/unsignedparity:

1;

/*奇偶/溢出标志*/unsignedhalf_carry:

1;

/*半进位标志*/unsignednegative:

1;

/*减标志*/}flags;

(4)可以用%d、%x、%u和%o等格式字符,以整数形式输出位段。

(5)在数值表达式中引用位段时,系统自动将位段转换为整型数。

例子:

voidmain({flags.sign=12;printf("%d\n",flags.sign;printf("%d\n",sizeof(flags;}[Return]

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 机械仪表

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1