☀️光天化日学C语言☀️(13)- 位运算概览 | 开启位运算的征程

举报
英雄哪里出来 发表于 2021/07/16 07:29:14 2021/07/16
【摘要】 开启位运算的征程

一、前言

  本文作者是从 2007 年开始学 C语言 的,不久又接触了C++,基本就是 C/C++ 技术栈写了 14 年的样子,不算精通,但也算差强人意。著有《夜深人静写算法》系列,且承诺会持续更新,直到所有算法都学完。主要专攻 高中 OI 、大学 ACM、 职场 LeetCode 的全领域算法。由于文章中采用 C/C++ 的语法,于是就有不少读者朋友反馈语言层面就被劝退了,更何况是算法。
  于是,2021 年 06 月 12 日,《光天化日学C语言》 应运而生。这个系列文章主要服务于高中生、大学生以及职场上想入坑C语言的志同道合之人,希望能给祖国引入更多编程方面的人才,并且让自己的青春不留遗憾!
  这一章的主要内容是聊一聊二进制和位运算。

二、人物简介

  • 第一位登场的就是今后会一直教我们C语言的老师 —— 光天。
  • 第二位登场的则是今后会和大家一起学习C语言的没什么资质的小白程序猿 —— 化日。

三、再谈二进制


[^_^]:
* 二进制就是逢二进一,计算机中的存储采用的就是二进制。

  • 在计算机中,非零即一。

1、二进制数值表示

  • 例如,在计算机中,我们可以用单纯的 0 和 1 来表示数字。

1、101、1100011、100101010101 都是二进制数。
123、423424324、101020102101AF 则不是,因为有 0 和 1 以外的数字位。

  • 一般为了不产生二义性,我们会在数字的右下角写上它的进制,例如:
  • 101 0 ( 10 ) 1010_{(10)}

  • 代表的是十进制下的 1010,也就是十进制下的 “一千零一十”。
  • 101 0 ( 2 ) 1010_{(2)}

  • 代表的是二进制下的 1010,也就是十进制下的 “十”。

2、二进制加法

二进制加法采用从低到高的位依次相加,当相加的和为2时,则向高位进位。

  • 例如,在二进制中,加法如下:$$1_{(2)} + 1_{(2)} = 10_{(2)} \ 1_{(2)} + 0_{(2)} = 1_{(2)} \ 0_{(2)} + 1_{(2)} = 1_{(2)} \ 0_{(2)} + 0_{(2)} = 0_{(2)} $$

3、二进制减法

二进制减法采用从低到高的位依次相减,当遇到 0 减 1 的情况,则向高位借位。

  • 例如,在二进制中:减法如下:$$1_{(2)} - 1_{(2)} = 0_{(2)} \ 1_{(2)} - 0_{(2)} = 1_{(2)} \ 10_{(2)} - 1_{(2)} = 1_{(2)} \ 0_{(2)} - 0_{(2)} = 0_{(2)} $$
  • 而我们今天要讲的位运算正是基于二进制展开的。

四、位运算简介

  • 位运算可以理解成对二进制数字上的每一个位进行操作的运算。
  • 位运算分为 布尔位运算符 和 移位位运算符。
  • 布尔位运算符又分为 位与(&)、位或(|)、异或(^)、按位取反(~);移位位运算符分为 左移(<<) 和 右移(>>)。
  • 如图所示:
  • 接下来几天,每天都会更新一篇,对每个位运算符的详细解读,并且配有例题。

五、位运算概览

  • 今天,我们先来对位运算进行一个初步的介绍。后面会对每个运算符的应用做详细介绍,包括刷题的时候如何运用位运算来加速等等。

1、布尔位运算

  • 对于布尔位运算,总共有四个,如下表所示:
C语言运算符表示 含义 示例
& 位与 x & y
| 位或 x | y
^ 异或 x ^ y
~ 按位取反 x ~ y

1)位与

  • 位与就是对操作数的每一位按照如下表格进行运算,对于每一位只有 0 或 1 两种情况,所以组合出来总共 2 2 = 4 2^2 = 4 种情况。
左操作数 右操作数 结果
0 0 0
0 1 0
1 0 0
1 1 1

#include <stdio.h>
int main() {
    int a = 0b1010;           // (1)
    int b = 0b0110;           // (2)
    printf("%d\n", (a & b) ); // (3)
    return 0;
}
  • ( 1 ) (1) 在C语言中,以0b作为前缀,表示这是一个二进制数。那么a的实际值就是 ( 1010 ) 2 (1010)_2
  • ( 2 ) (2) 同样的,b的实际值就是 ( 0110 ) 2 (0110)_2
  • ( 3 ) (3) 那么这里a & b就是对 ( 1010 ) 2 (1010)_2 ( 0110 ) 2 (0110)_2 的每一位做表格中的&运算。
  • 所以最后输出结果为:
2
  • 因为输出的是十进制数,它的二进制表示为: ( 0010 ) 2 (0010)_2
  • 注意:这里的 前导零 可有可无,作者写上前导零只是为了对齐以及让读者更加清楚位与的运算方式。

2)位或

  • 位或的运算结果如下:
左操作数 右操作数 结果
0 0 0
0 1 1
1 0 1
1 1 1

  • 我们来看以下这段程序:
#include <stdio.h>
int main() {
    int a = 0b1010;
    int b = 0b0110;         
    printf("%d\n", (a | b) );
    return 0;
}
  • 以上程序的输出结果为:
14
  • 即二进制下的 ( 1110 ) 2 (1110)_2

3)异或

  • 异或的运算结果如下:
左操作数 右操作数 结果
0 0 0
0 1 1
1 0 1
1 1 0

  • 我们来看以下这段程序:
#include <stdio.h>
int main() {
    int a = 0b1010;       
    int b = 0b0110;          
    printf("%d\n", (a ^ b) ); 
    return 0;
}
  • 以上程序的输出结果为:
12
  • 即二进制下的 ( 1100 ) 2 (1100)_2

4)按位取反

  • 按位取反其实就是 0 变 1, 1 变 0。
  • 同样,我们来看一段程序。
#include <stdio.h>
int main() {
    int a = 0b1;
    printf("%d\n", ~a );
    return 0;
}

2、移位位运算

  • 对于移位位运算,总共有两个,如下表所示:
C语言运算符表示 含义 示例
<< 左移 x << y
>> 右移 x >> y

1)左移

  • 其中x << y代表将二进制的 x x 的末尾添加 y y 个零,就好比向左移动了 y y 位。
  • 比如 ( 1011 ) 2 (1011)_2 左移三位的结果为: ( 1011000 ) 2 (1011000)_2

2)右移

  • 其中x >> y代表将二进制的 x x 从右边开始截掉 y y 个数,就好比向右移动了 y y 位。
  • 比如 ( 101111 ) 2 (101111)_2 右移三位的结果为: ( 101 ) 2 (101)_2

通过这一章,我们学会了:
  1)位与 & ;
  2)位或 |
  3)异或 ^;
  4)按位取反 ~;
  5)左移 <<;
  6)右移 >>;

  • 希望对你有帮助哦 ~ 祝大家早日成为 C 语言大神!

课后习题


📢博客主页:https://blog.csdn.net/WhereIsHeroFrom
📢欢迎各位 👍点赞 ⭐收藏 📝评论,如有错误请留言指正,非常感谢!
📢本文由 英雄哪里出来 原创,转载请注明出处,首发于 🙉 CSDN 🙉
作者的专栏:
  👉C语言基础专栏《光天化日学C语言》
  👉C语言基础配套试题详解《C语言入门100例》
  👉算法进阶专栏《夜深人静写算法》

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。