C之位运算(十五)-创新互联

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

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:空间域名、网络空间、营销软件、网站建设、沧县网站维护、网站推广。

C之位运算(十五)

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

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

#include 

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;编译后结果如下:

C之位运算(十五)

        我们可以看到我们的分析是对的,第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 

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了。因为我们这块是位运算,所以没有短路规则。我们来看看编译结果:

C之位运算(十五)

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

C之位运算(十五)


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

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

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享名称:C之位运算(十五)-创新互联
本文来源:http://myzitong.com/article/ddgdjd.html