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。

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

时间: 2024-11-05 19:43:18

C之位运算(十五)的相关文章

第十六天:C语言进阶之位运算及内嵌汇编

位运算在驱动开发中是经常遇到的,尤其是置0和置1.既要指定的位数发生变化,又不能改变其它位的值.还要高效率的编写代码.这时候技巧就很重要了.在位运算中有几个符号: |  按位或 & 按位与  ^ 异或  -按位非 1 #include<stdio.h> 2 3 int main() 4 { 5 int a = 0x1101; 6 int b = 0x1011; 7 int c = 9; 8 printf("a | b is %x\n",a | b); 9 print

第十五章 枚举类型和位标志

1. 概述 本章内容包括 枚举类型.位标志 以及 为枚举类型添加方法. 2. 主要内容 2.1 枚举类型 枚举类型定义了一组“符号名称/值”配对. 枚举类型的好处包括: ① 可以使程序更容易编写.阅读和维护. ② 枚举类型是强类型的,有编译器检测. 编译枚举类型时,C#编译器会把每个符号转换成类型的一个常量字段. System.Enum类型有一个名为GetUnderlyingType的静态方法,返回用于容纳一个枚举类型的值的基础类型. Enum.GetUnderlyingType(typeof(

第十五章 文件属性类的实现

                  第十五章    文件属性类的实现        根用户的权限也不能是无限大.必须考虑到保护用户的隐私!用户的文件内容.程序代码可设置为根用户也不能观看,只能是文件拥有者可以查看.修改.但根用户可以删除一切非根用户的文件.也可以查看用户的目录.所以,i_mode字符更改如下:      BU16 i_mode; // 描述文件的访问权限:文件的读.写.执行权限  // i_mode.15-13  ftype; 文件类型: 0-符号软连接文件, // 1-硬连接文

每日算法之二十五:Divide Two Integers

Divide two integers without using multiplication, division and mod operator. 不使用乘法.除法和求模运算求两个数相除. class Solution { public: long long internalDivide(unsigned long long dividend,unsigned long long divisor) { if(dividend<divisor) return 0; int result =

位运算 使用技巧

位运算简介及实用技巧(一):基础篇 什么是位运算? 程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算说穿了,就是直接对整数在内存中的二进制位进行操作.比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算.举个例子,6的二进制是110,11的二进制是1011,那么6 and 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理): 110 AND 1011 ---------- 0010  -->  2 由于位运算

位运算基本概念及简单运用

C语言提供了六种位运算符: &     按位与    |      按位或    ^      按位异或    ~      取反    <<    左移,相当与*2    >>    右移,正数高位补0,负数由计算机决定 循环左移k次 (x<<k) | (x >> (32-k)), 循环右移k次 (x>>k) | (x << (32-k)) 当然常常应为优先级问题而犯错~~~ 优先级及口诀如下 优先级别 运算符 记忆口诀 1

2015私人阅读十五佳

2015私人阅读十五佳 2015私人阅读十五佳 统计 私人阅读十五佳 非暴力沟通 沟通的艺术 看入人里看出人外 父母效能训练手册 对伪心理学说不 精益创业 新创企业的成长思维 枪炮病菌与钢铁 人类简史 从动物到上帝 现代世界史 狂热分子 群众运动圣经 独裁者手册 社会主义 经济与社会学的分析 编码 隐匿在计算机软硬件背后的语言 儒家哲学 水浒传注评本 蒋介石与现代中国 统计 2015年一共读完46本,其中五星18本,占比40%:四星17本,占比近40%:三星7本:两星4本.阅读主题以社科.历史.

位运算与流程控制语句5

文件命名方法: 驼峰命名 classNum 下划线命名 class_num A 65 Z 90a 97 z 122 baxuexi de zuo cheng bijibu yao wangji mei tian fuxi qianyi tian xue xi de.wen gu er zhi xin bu jiu geng you yi si le ma. 一.位运算 符号 描述 运算规则 & 按位与 屏蔽某些二进制位(置零) | anwei或 两个都为零结果都为0 作用:把某些二进制位 置1

OpenGL教程翻译 第十五课 相机控制(二)

OpenGL教程翻译 第十五课 相机控制(二) 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) Background 在这一节中我们将使用鼠标来控制相机的方向,从而得我们的相机控制更加完善.相机有不同的自由程度,这与其设计有关.在本教程中我们将要实现的是与第一人称游戏中相似的相机控制(如枪战类游戏).这意味着我们将可以使相机完成360度的旋转(绕着Y轴),这与我们的头部向左转向右转.身体转一整圈类似.除此之外我们也能使相机向上或者向下倾斜以获得更好的向