前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【编程基础】如何了解c语言中的位运算?

【编程基础】如何了解c语言中的位运算?

作者头像
程序员互动联盟
发布2018-03-14 17:03:59
1.7K0
发布2018-03-14 17:03:59
举报
文章被收录于专栏:程序员互动联盟
计算机的各种运算最小单位是字节,但是有时候只对某个位(bit)感兴趣,C语言提供了一些列位运算符来完成这个任务。这些操作非常重要,尤其是在嵌入式开发中会常常用到,这也是为什么嵌入式基本上都是选用C语言来开发的重要原因之一。

C语言的位运算有一下六中: & 按位与 | 按位或 ^ 按位亦或 ~ 按位取反 << 左移 >> 右移

按位与& 两个对应的位为1,运算后对应位为1,否则为0,比如:10101100 & 01101001 = 00101000。

按位或| 两个对应位中只要有一个为1,运算后对应位就为1,否则为0,比如:10101100 | 01101001 = 11101101。

按位亦或^ 两个对应位中如果不同,运算后对应位就为1,否则相同就为0,比如:10101100 ^ 01101001 = 11000101。

按位取反~ 将原来对应位取反,1变0,0变1。这个是一个单目运算,也就是只需要一个操作数,比如:~10101100 = 01010011。

左移<< 将整个位左移指定位数,比如:10101100 << 3,结果为01100 000。前面的三位101被移走,后面补充3个0。

右移>> 将整个位右移指定位数,比如:10101100 >> 3,结果为多少?右移有点不一样,它分逻辑右移和算术右移。如果是逻辑右移,向右移动后,左边补0;如果是算术右移,则左边最高位是0时,就补0,如果左边最高位是1,则根据编译器不同可能会不同。比如:逻辑右移:10101100 >> 3,结果为000 10101。右边的100被移走,左边补0;算术右移:10101100 >> 3,结果可能为111 10101,也可能为000 10101。当然右边的100还是被移走。

以上基本的位运算其实很简单,很多人一看就理解了,但是要灵活应用却不是那么简单的。比如有群友提出清除位是怎么回事,其实就是这个为位运算了,将一个数的某一个位设置为0。比如我们要将10101100这个二进制位的左边第三位清除,则可以用如下办法:10101100 & 11011111。

一般实际编程中都用一个mask来清除和设置。像上面这个问题,我们定义一个mask为0x20的数(00100000),要设置左边第三位,者只需要10101100 | mask;要清除时,用10101100 & ~mask即可。这样所有位我们都可以定义mask来操作。这个在嵌入式上用的非常广泛,比如设置和清除寄存器。类似的应用还有很多,下面举一个例子:

位映射:

unsigned char data[32]; #define BIT_SET(a, n) (((a)[(n) >> 3]) |= (1 << ((n) & 0x07))) #define BIT_GET(a, n) ((((a)[(n) >> 3]) >> ((n) & 0x07)) & 0x01) #define BIT_CLR(a, n) (((a)[(n) >> 3]) &= (~(1 << ((n) & 0x07))))

它可以用一个位来记录某个对应的操作。

求绝对值:

int myabs(int n) { int f = n >> 31; n ^= f; n -= f; return n; }

计算一个整数中有多少位是1:

int count(unsigned int v) { v -= (v>>1) & 0x55555555; v = (v & 0x33333333) + ((v>>2) & 0x33333333); v = (v + (v>>4)) & 0x0F0F0F0F; v += v>>8; v += v>>16; return v & 0x3F; }

颠倒一个字节的位序:

unsigned char reverse(unsigned char b) { b = (b << 4) + (b >> 4); b = ((b & 0x33) << 2) + ((b & 0xCC) >> 2); b = ((b & 0x55) << 1) + ((b & 0xAA) >> 1); return b; }

奇偶校验计算:

static int Parity(int val) { int parity = val; parity ^= parity >> 16; parity ^= parity >> 8; parity ^= parity >> 4; parity ^= parity >> 2; parity ^= parity >> 1; return parity & 0x00000001; }

还有更复杂的汉明码解码等就不在这里举例了,位运算本身是很简单的,但是真正应用起来是非常复杂的。但是他的效率也很高,同样一个任务,往往用位运算能提高速度。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2015-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员互动联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档