找回密码
 注册

QQ登录

只需一步,快速开始

查看: 674|回复: 0

21春吉大《c语言程序设计》复习资料(九)

[复制链接]
发表于 2021-2-21 10:03:53 | 显示全部楼层 |阅读模式
吉大《C语言程序设计》拓展资源(九)
1、位运算符和位运算表达式
C语言中提供了如下6种的位运算符:
&    按位与
|       按位或
^      按位异或
<<    左移
>>    右移
~      按位取反
提示:只允许对整型、字符型数据进行位运算,而实型数据不能进行位运算。
2、位运算规则
A
B
A&B
A|B
A^B
~a

0
0
0
0
0
1

0
1
0
1
1
1

1
0
0
1
1
0

1
1
1
1
0
0

例9.1 若  a=(15)10=(00001111)2, b=(80)10=(01010000)10
则: a&b = 0000 0000,  a|b = 0101 1111,        
      a^b =01011111 ,         ~a = 1111 0000
3、位运算的应用
1)"按位与"运算经常用于将某些二进制位屏蔽掉。
例9.2 编写函数:使一个整数k中的低4位置0。
分析:用“与”运算实现:将k的低4位与0相与,其他位与1相与,即将 k与十六进制的 1110 相与。程序如下:
unsigned int_set(unsigned int  k)
{ k=k & 0x1110 ;   
return(k); }结论:任何二进制位与0相与能实现置0,与1相与该位保持不变。
2)"按位或"运算经常用与将某些二进制位 置 1。
例9.4:将一个字节的高4位置为1010并输出结果。
分析:直接用位运算符,可以很方便的置1、清0、翻转等,但无法直接实现置给定的值。可以用两步实现:首先将高4位清 0,然后与1010 0000相或。程序如下:
/*设 a 为待处理的数据,转换成二进制为00001000,b用来保存将a的高4位清0后的结果*/
main()
{ unsigned char a,b,c;   a=8;
b=a&0x0f; c=b|0xa0;    /*c用于保存最终结果*/
printf("%x",c);
}  
运行结果:10101000
3)按位异或运算经常用与将某些位翻转。
例9.5 编程实现,将一整数n的高8位翻转,低8位不变
分析:用“异或”运算实现,即高8位与1相异或,低8位与0相异或,也就是k与十六进制的ff00相异或。程序如下:
main()
{ int n=129;
printf("\n before  reset,n=%x",n);
n=n∧0xff00;
printf("\n after reset,n=%x",n);
  }   运行结果:
before reset,n=00000000 10000001
after reset,n=11111111 10000001           
结论:任何二进制位与0异或,保持不变;与1异或,对应位翻转。
4)左移、右移运算实现将一个数的各个二进制位向左、向右移若干位。
左移:将一个数的各个二进制位左移若干位,高位左移后舍弃,低位补0 。
若定义: int  a=8;   即a= 0000 1000     , 则语句a=a<<2;
将 a 的各二进制位左移 2 位,空出的低位补0。结果为:0010 0000
右移:将一个数的各个二进制位右移若个位,低位右移后舍弃,高位补 0还是补1,要区别有符号数还是无符号数:无符号数高位补0,有符号数高位补原符号位。         
若定义 unsigned int a=8;   即 00001000,
则语句  a=a>>2 ;将 a 的各二进制位右移 2 位,空出的高位补 0。结果为: 0000 0010
4、位段
1).? 位段的概念
以位为单位定义其长度的结构体成员。
2).位段的定义
例9.6若某个控制字长32位,分5段,每段的长度分别为:2 ,6 ,4 ,4 ,16位 ;每段存放一个信息,且第4段空出不用。可用如下结构体类型描述:
struct con_word
{ unsigned   a: 2;      /*位段a,长度为2*/
     unsigned  b: 6 ;     /*a,b,c为有名位段*/
     unsigned  c: 4;
     unsigned    : 4;     /*该位段为无名位段,表示这4位空间空出不使用*/
     int  i ;                     
    } data;
变量data 的存储结构如图 :
  a      b          c                         i           ……成员名
2      6          4        4               16          ……  长度
  3).位段的引用
    位段是结构体类型的某个成员,因此,位段的引用同结构体成员的引用方法相同。
    如:data.a=0x01;         /*给位段a赋值, */
        data.b=0x0a;           /*给位段b赋值*/
        data.i=12;               /*给位段 i赋值*/
        printf(“%02x,  %02x,  %4d”, data.a ,  data.b ,data.i );      
输出:  01, 0a,  12
    特别提示:使用位段时,要注意该位段的能表示的数据的范围。
5、位段的应用
编程模拟一个温度测控系统:从键盘输入模拟温度的采样值(0~255),该采样值与0.2相乘,得出实际温度值,根据该温度值,控制温度指示灯的亮与灭(从0度开始,温度每增加10度则多点亮一个指示灯);将该温度值与设定温度比较,当温度小于10度和高于40度时分别开启升温设备和降温设备,同时报警。反复以上过程,直至输入的测温值为300为止。
   分析:系统中需要控制的设备有:五个温度指示灯,升温设备,降温设备,报警设备。因此可用如下的结构体变量word表示该系统的控制字,其成员构成如下:
(1)无符号整型tem1 用来存放输入的温度采样值(0~255),若每个刻度代表0.2度,则可以测量的温度范围为0~51度。浮点类型的成员tem2用来存放tem1成员转换成的温度值。
(2)四个位段存放(要输出的)控制数据。其中,位段lmp 宽度为5,控制五个温度指示灯,值为1时灯亮,为0时灯不亮。其余的3个位段sw1、sw2、alm宽度均为1,分别控制升温设备、降温设备和报警设备,都是为“1”时开启,为0时关闭。
函数sample()实现测温采样:通过键盘输入模拟测温数据,并转换成实际温度值。
函数 control()实现输出控制:通过屏幕显示和喇叭鸣笛的方式输出温度值、温度级别、设备开关情况和报警状态。
#define ON 1
#define OFF 0
struct ctrl_type
{ unsigned char tem1;
  float tem2;
  unsigned lmp:5;
unsigned sw1:1;
  unsigned sw2:1;
  unsigned alm:1;
};
main()
{void sample(struct ctrl_type *wp);
void control(struct ctrl_type *wp);
struct ctrl_type word;
while(1)
{sample(&word);   /*温度采样*/
                                 / *生成温度指示灯控制位*/
  word.lmp=~(0xffff<<(int)word.tem2/10);
                /*生成升温、降温设备及报警设备的控制位*/
  if(word.tem2<10)
     {word.alm=ON; word.sw1=ON;   word.sw2=OFF;}
  else if(word.tem2<40)  
            {word.sw1=word.sw2=word.alm=OFF;}
       else {word.sw1=OFF;word.sw2=word.alm=ON;}
  control(&word);    }    }   /*输出控制字,控制各设备*/
void sample(struct ctrl_type *wp)
{printf("\ninput test data(0~255)(300 for end):");
scanf("%u",&wp->tem1);
if(wp->tem1==300) exit(0);
wp->tem2=wp->tem1*0.2;
}
说明:
1)函数sample()实现测温采样:通过键盘输入模拟测温数据,并转换成实际温度值。
2)函数 control()实现输出控制:通过屏幕显示和喇叭鸣笛的方式输出温度值、温度级别、设备开关情况和报警状态
void control(struct ctrl_type *wp)
{char i,m;
printf("\n%6s %6s %4s %4s %6s", "degree", "lamp", "sw1", "sw2", "alarm");
printf("\n %6.1f ",wp->tem2);
for(i=0,m=0x10;i<5;i++,m>>=1)
  printf("%c",wp->lmp&m?'*':' ');   
           /*用‘*’表示温度指示灯亮*/
printf("%4s",wp->sw1?"ON":"OFF");
          /*用ON表示开启,用OFF表示关闭*/
printf("%4s",wp->sw2?"ON":"OFF");
printf("%6s",wp->alm?"ON\x07":"OFF\x20");
}
转载注明  无忧答案网

QQ|手机版|小黑屋|网站地图|无忧答案网 ( 冀ICP备18010495号-1 )

GMT+8, 2024-5-3 14:14

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表