温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C之位运算(十五)

发布时间:2020-07-22 06:02:29 来源:网络 阅读:2168 作者:上帝之子521 栏目:编程语言

        我们在嵌入式的开发中难免会遇到 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 <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;编译后结果如下:

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

C之位运算(十五)

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

C之位运算(十五)

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


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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI