查看: 1794|回复: 0
打印 上一主题 下一主题

移位运算的左移。

[复制链接]
跳转到指定楼层
沙发
发表于 2015-9-24 08:13:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
移位运算的左移。
     前面讲的“与,或,异或”运算,漏讲了它们的简写格式的内容,在本节开始之前先把这部分内容补上。在“与,或,异或”这些运算中,当赋值语句左边的“保存变量”是参与运算的变量本身时,也存在简写的语法格式,比如:
     a&=0x01;  //相当于a=a&0x01;
       a|=0x01;  //相当于a=a|0x01;
       a^=0x01;  //相当于a=a^0x01;

       现在正式开始本节内容“移位运算的左移”。左移的运算符号是“<<”,语法格式如下:
     保存变量=被移数<<n;
       其中n代表“被移数”需要左移的位数。
     整句语法的含义是:“被移数”的二进制格式数据被整体往左边移动了n位,原来高n位数据被直接覆盖,新空出的低n位数据填入0。最后把移位结果存入“保存变量”。
     现在举一个完整的例子来分析“按位取反”运算的规律。有2个unsigned char类型的变量a和b,a的初始值是十进制数5,a=a<<1的结果是多少?b的初始值也是十进制数5,b=b<<2的结果是多少?
分析步骤如下:
     第一步:先把参与运算的数转换成二进制的格式。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制5的二进制格式是:00000101。
     第二步:
(1)将5的二进制数整体往左边移动1位:
                     原来是:00000101
        整体往左移动1位后变成:00001010
        把二进制的00001010转换成十六进制是:0x0A。转换成十进制是10。所以a初始值是5,左移1位后的结果是10.
(2)将5的二进制数整体往左边移动2位:
                     原来是:00000101
        整体往左移动2位后变成:00010100
        把二进制的00010100转换成十六进制是:0x14。转换成十进制是20。所以b初始值是5,左移2位后的结果是20.
        仔细观察上述两个例子,发现了一个重要的规律:某数左移1位相当于此数乘以2,左移多少位相当于乘以多少个2.比如上述例子中5左移1位相当于5乘以2,结果等于10。而5左移2位相当于5乘以2再乘以2,5*2*2的结果等于20。既然左移1位相当于某个数乘以2,那么为什么不直接用乘法来替代左移呢?原因是一条左移语句的运算速度比一条乘法语句的运算速度要快很多倍。
     左移是在单片机项目中很常用的语法,也经常应用在一些数据类型之间的合并中。比如有两个unsigned char单字节的类型数据H和L,H的初始值是十六进制的0x12,L的初始值是十六进制的0x34,要将两个单字节的H和L合并成一个unsigned int双字节的数据c,其中H是高8位字节,L是低八位字节,合并成c后,c的值应该是十六进制的0x1234,此程序如何写?就需要用到左移。程序分析如下:
unsigned char H=0x12;  //单字节
unsigned char L=0x34;  //单字节
unsigned int c; //双字节
c=H;//c的低8位被H覆盖,也就是c的低8位得到了H的各位值。
c=c<<8; //及时把c的低8位移动到高8位,同时c原来的低8位被填入0
c=c+L;//此时c再加L,c的低8位就L的值。
      程序运行结果:c就等于十六进制的0x1234,十进制是4660。
      再多讲一下知识点,左移也存在简写格式,比如:
d<<=1; //就相当于d=d<<1;
e<<=2; //就相当于e=e<<2;
         现在编写一个程序来练习刚才讲到的主要内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/


  unsigned char a=5;
  unsigned char b=5;

  unsigned char H=0x12;  //单字节
  unsigned char L=0x34;  //单字节
  unsigned int c; //双字节

  a=a<<1; //a左移1位,从原来的5变成了10.
  b=b<<2; //b左移2位,从原来的5变成了20.


  c=H;     //c的低8位被H覆盖,也就是此时c的低8位得到了H的各位值。
  c=c<<8;  //及时把c的低8位移动到高8位,同时c原来的低8位被填入0
  c=c+L;   //此时c再加L,c的低8位就L的值。此时c得到了H和L合并而来的值。


  GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示
  GuiWdData1=b;   //把b这个变量放到窗口变量1里面显示
  GuiWdData2=c;   //把c这个变量放到窗口变量2里面显示



/*---C语言学习区域的结束---------------------------------------------------------------------------*/
   while(1)  
   {
      initial();
      key_service();
      display_service();
   }

}

复制代码

        查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0。上坚鸿51学习板观察程序执行的结果如下:
     变量a为10 (十六进制是0x0A,二进制是00001010)。
     变量b为20(十六进制是0x14,二进制是00010100)。
     变量c为4660(十六进制是0x1234,二进制是0001 0010 0011 0100)。
     下节预告:移位运算的右移。
(未完待续)转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

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