码迷,mamicode.com
首页 > 其他好文 > 详细

C之位运算(十五)

时间:2018-04-11 00:18:02      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:C语言   位运算符   

        我们在嵌入式的开发中难免会遇到 C 语言中的位运算符,因为我们需要效率,而位运算恰好效率比别的运算符效率高多了。位运算符直接对 bit 为进行操作,其效率最高。常见的位运算操作如下

技术分享图片

        我们在左移和右移时必须要注意:1、左操作数必须为整数类型,char 和 short 被隐式转换为 int 后进行移位操作;2、右操作数的范围必须为:[0,31];3、左移运算符 << 将运算数的二进制位左移,规则是高位丢弃低位补0;4、右移运算符 >> 把运算数的二进制位右移,规则是高位补符号位低位丢弃。

        比如 0x1 << 2 + 3 的值会是多少呢?我们猜想有这么几种情况:1、先算 0x1 << 2 再把中间结果加 3,最终结果为 7;2、先算 2 + 3,所以结果为 32;3、这么混合的运算会出错。我们来看个示例代码,来看看编译器是如何处理的,代码如下:

#include <stdio.h>

int main()
{
    printf("%d\n", 3 << 2); 
    printf("%d\n", 3 >> 1); 
    printf("%d\n", -1 >> 1); 
    printf("%d\n", 0x01 << 2 + 3);
    
    return 0;
}

        我们先来分析下这个代码,第5行 3 << 2 ==> 11 << 2 ==> 1100 ==> 12;第6行 3 >> 1 ==> 11 >> 1 ==> 1;编译后结果如下:

技术分享图片

        我们可以看到我们的分析是对的,第8行执行的是我们之前分析的第2种结果。

        我们在 C 语言中应避免位运算符、逻辑运算符和数学运算符同时出现在一个表达式中;但位运算符、逻辑运算符和数学运算符需要同时参与运算时,尽量使用括号()来表达计算次序;左移 n 为相当于乘以 2 的 n 次方(同理右移相当于除),但效率比数学运算符高。

        我们下来看个实现宏函数交换的功能,这也是笔试中经常会遇到的一个题目,代码如下:

#define SWAP1(a, b)    {                          int t = a;             a = b;                 b = t;             }

        这是我们最常用的一种写法,但是它需要一个额外变量。我们下面来看个不需要借助额外变量的版本就可以完成的宏函数,代码如下:

#define SWAP2(a, b)    {                          a = a + b;             b = a - b;             a = a - b;         }

        第4 行相当于 b = (a + b) - b ==> b = a;第5行相当于 a = (a + b) - b ==> a = (a + b) - a ==> a = b;这种也可以完成交换功能,但是它的效率似乎不是那么的高,因为要借助于数学运算。我们再来实现一个基于位运算实现的,代码如下:

#define SWAP3(a, b)    {                          a = a ^ b;             b = a ^ b;             a = a ^ b;         }

        我们上面的代码效率是非常高的,我们来分析下,第 4 行相当于 b = (a ^ b) ^ b ==> b = a; 第5行相当于 a = (a ^ b) ^ b ==> a = (a ^ b) ^ a ==> a = b;这样也实现了交换的功能。

        位运算与逻辑运算不同之处:1、位运算没有短路规则,每个操作数都参与运算;2、位运算的结果为整数,而不是 0 或 1;3、位运算的优先级高于逻辑运算优先级。

        我们来看看下面这个示例代码:

#include <stdio.h>

int main()
{
    int i = 0;
    int j = 0;
    int k = 0;
    
    if( ++i | ++j & ++k )
    {
        printf("Run here...\n");
    }
    
    printf("i = %d\n", i);
    printf("j = %d\n", j);
    printf("k = %d\n", k);
    
    return 0;
}

        我们分析下,第 9 行执行完,i、j、k分别就是1了。因为我们这块是位运算,所以没有短路规则。我们来看看编译结果:

技术分享图片

        是如我们分析的那样,如果我们第9行换成 if( ++i || ++j && ++k ) 这样,那么便是 i = 1,j = 0, k = 0 了,打印如下

技术分享图片

        通过我们今天学习的位运算符,总结如下:1、位运算符只能用于整数类型;2、左移和右移运算符的右操作数范围必须为[0, 31];3、位运算没有短路规则,所有操作数均会求值;4、位运算的效率高于四则运算和逻辑运算;5、运算优先级:四则运算 > 位运算 > 逻辑运算后面我们会继续对 C 语言的学习。


         欢迎大家一起来学习 C 语言,可以加我QQ:243343083

C之位运算(十五)

标签:C语言   位运算符   

原文地址:http://blog.51cto.com/12810168/2096718

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!