您的当前位置:首页正文

C语言位运算中鲜为人知的事

来源:华佗健康网
第17卷第5期 2014年5月 软件工程师SOFTWARE ENGINEER 、,01.17 NO.5 Mav 2014 文章编号:1008—0775(2014)一05—20—02 C语言位运算中鲜为人知的事 周 岚 (江苏联合职业技术学院徐州财经分院,江苏徐州221008) 摘要:在很多系统程序中常要求在位(bit)一级进行运算或处理。C语言提供了位运算的功能,这使得C语言也能 像汇编语言一样用来编写系统程序。位运算说的简单一些,就是直接对整数在内存中的二进制位进行操作。希望通过本 文让大家了解位运算中鲜为人知的事情。 关键词:位运算;规则;左移;右移;可移植 中图分类号:TP312 文献标识码:A C Language in the Operation of Those Little-known ZH0ULan (Jian ̄uLianhe TechnicalInstituteXuzhouFinancialSchoolofJiangsuyuzhou 221008,China) Abstract:In many system program often requires(bit)in a computing or processing.C language provides a calculation function,which makes the C language can be the same as the assembly language used to write the program.Bit operation that simple,just to integer in binary bits in memory operation.Hope that through this article to let everybody know the li ̄le— known things bit operation. Keywords:bit operations;rules;left;right;transplantation l引言(Introduction) 程序中的所有数在计算机内存中都是以二进制的形式储 进制位进行操作。比如,and运算本来是一个逻辑运算符, 但整数与整数之间也可以进行and运算。举个例子,6的二进 制是110,11的二进制是1011,那么6 and 11的结果就是2, 它是二进制对应位进行逻辑运算的结果(0表示False,1表示 True,空位都当0处理)…。 在很多系统程序中常要求在位(bit)一级进行运算或处 理。C语言提供了位运算的功能,这使得C语言也能像汇编语 言一样用来编写系统程序。 在C语言中常用的位运算操作如下: 操作符 & 的汇编代码,该段代码起一个名称宏名,其使用与汇编指令 类似。  存的。位运算说的简单一些,就是直接对整数在内存中的二 例1:#define SETAA 1(X,y)((x)I=(y)) #define sETAA2(x,Y) ((x)&= (y)) #define SETAA3(x,Y) ((x) =(y)) #define SETAA4(x,Y) ((x)&(y)) 3位操作尽量使用unsigned char,而不是char(Bit operation as far as possible the use of unsigned char,not char) 如果你使用char,那么一个普通的字符,0xe3,因为首位 是1,所以当它被转换为1位长时,成了0xfffffe3,而不是我 们想要的0x000000e3,因为它是一个有符号的负数。 让我们来看一下这个例子。 例2: #include<stdlib.h> #include<stdio.h> 1 ^ >> << 作用 位逻辑与 位逻辑或 位逻辑异或 位逻辑反 右移 左移 , int main() {//char buf[10]={0}; 按位运算是对字节或字中的实际位进行检测、设置或移 位,它只适用于字符型和整数型变量以及它们的变体,对其 他数据类型不适用。下面让我们一起来看看位运算鲜为人知 的事情。 unsigned char buf[10l={0}; char sbuf[10]={0}; buf[O]=Oxe3; 2位操作应该先用宏定义好后再使用(Operation should be the first to use the macro definition buf[1]=0xb4; sbuf[0]=0xe3; sbuf[1]=0xb4; unsigned short pidl,pid2,pid3; afteruse) 什么是宏定义呢?宏定义是指:一段具有一定独立功能 第17卷第5期 周岚:C语言位运算中鲜为人知的事 21 /*bit operations with unsigned chars*/ prinff(“bit operations with unsigned chars:\n”); pidl=(buf[0]&0xlf): pid2=((buf[0】&0xlf)<<8); pid3=((buf[0l&0xlf<<8)lbuf[1】} Printf(“pidl:%x\n”,pid1); Printf(“pid2=%2x\n”,pid2); Prinff(“pid3=%2x\n”,pid3); /*bit operations with signed chars*/ printf(“bit operations with signed chars:\n”); pid1=(sbuf[0]&0x1f); pid2=((sbuf[Ol&0xlf)<<8); pid3=((sbuf[0]&0x1f)<<8)[sbuf[1] printf(“pidl=%x\n”,pid1); printf(“pid2=%2xkn”,pid2); printf(“pid3=%2x\n”,pid3);} 结果如下: [shaoting@serverbj6:/user/shaoting/DVB-TI¥./ a.out bit operations with unsigned chars: pidl=3 pid2=300 pid3=3b4 bit operations with signed chars: pidl=3 pid2=300 pid3:fib4 可见,pid3的两次取值,因为一个是针对unsigned char 的buffer,另一个是针对char的buffer而使结果不同。 4移位运算符(Shift operator) 在使用移位运算符时,我常常会思考这样两个问题: (1)在向右移位时,空出的位是由0填充,还是由符号位 填充? (2)移位计数允许的取值范围是什么? 第一个问题的答案很简单,但有时却是与具体的C语言实 现有关。如果被移位的对象是无符号数,那么空出的位将被0 填充 。如果被移位的对象是有符号数,那么c语言实现既可 以用0填充空出的位,也可以用符号位的副本填充空出的位。 我们如果关注向右移位时空出的位,那么可以将操作的变量 声明为无符号类型,那么空出的位都会被设置为0。 第二个问题也同样简单:如果被移位的对象长度是n位, 那么移位计数必须大于0,小于n。不可能做到在单次操作中 将某个数值中的所有位都移出来。 举例:如果一个int型数是32位,n是一个int型整数,那 么n<<31和n>>0这样写都是合法的,而n<<32就不合法了, 当然,n>>一1一样也是不合法的。 我们再来看看下面的例子。 例3: Ox01<<2+3该式的结果是多少? 这个表达式的结果是多少?是7吗?测试的结果不是7, 正确的结果应该是32,这是为什么呢?因为“+”号的优先级 比移位运算的优先级高,在32位系统下,再把这个例子改写 一下: Ox01<<2+30,或者改成:Ox01<<2-4,这样行吗?答 案是不行。一个整型数长度为32位,左移32位发生了什么事 情?当然是溢出了,上面才讲过。同样左移一27所以,不管 是左移还是右移,所移的位数都是有讲究的。左移和右移的 位数不能大于和等于数据的长度,不能小于0。 另外,C语言中位移操作分为算术位移和逻辑位移,二者 都表示为<<和>>运算符。 进行左移操作时,算术位移和逻辑位移都在结果右端 补0。但是右移时有所不同,算术位移在左端填充符号位(正 数为0,负数为1),逻辑位移在左端补0。位移运算的特性结 合C算术运算时类型提升特性,很容易出错 】。让我们再看 一个例子。 例4: unsigned short a=0xffe5; unsigned char b=(a<<20)>>26; 上述代码执行结果为b=Oxff。实际上(a<<20)>> 26的结果为0xfffffff。其原因为: a<<20的执行结果超出unsigned short上限,中间结果 自动提升为int型(注意:这里是int型),其后的>>26操作已 经变为算术位移了,于是结果的左边被补上了l,最终导致结 果错误。 上述代码应该修正如下 unsigned short a=0xffe5; unsigned int tmep=a;//强制提升为unsigned int,杜绝自动提升 unsigned char b=(temp<<20)>>26; 结果b=Oxbf,结果正确。 5结论(Conclusion) 综上所述,在进行位移操作时,一定要小心上溢,建议 在进行左移时先强制将无符号数(unsigned short,unsigned char)转换为unsigned int,再进行运算。 参考文献(References) [1】谭浩强.c语言程序设计【M】.北京:清华大学出版社,201O: 45-46. [21魏书堤,赵辉煌.c语言二进制位运算教学设计IJ]倩阳师范学 院学报,2013(6):149—152. [3】赵忠孝,杨亚蕾.对c语言指针教学问题的探究U].计算机教 育,2009(19):78—79. 作者简介: 周 岚(1977一),女,硕士,讲师.研究领域:计算机程序设 计,数据库. 

因篇幅问题不能全部显示,请点此查看更多更全内容