光天化日学C语言(13)- 位运算概览 | 开启位运算的征程
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了光天化日学C语言(13)- 位运算概览 | 开启位运算的征程相关的知识,希望对你有一定的参考价值。
📢博客主页:https://blog.csdn.net/WhereIsHeroFrom
📢欢迎各位 👍点赞 ⭐收藏 📝评论,如有错误请留言指正,非常感谢!
📢本文由 英雄哪里出来 原创,转载请注明出处,首发于 🙉 CSDN 🙉
作者的专栏:
👉C语言基础专栏《光天化日学C语言》
👉C语言基础配套试题详解《C语言入门100例》
👉算法进阶专栏《夜深人静写算法》
文章目录
一、前言
本文作者是从 2007 年开始学 C语言 的,不久又接触了C++,基本就是 C/C++ 技术栈写了 14 年的样子,不算精通,但也算差强人意。著有《夜深人静写算法》系列,且承诺会持续更新,直到所有算法都学完。主要专攻 高中 OI 、大学 ACM、 职场 LeetCode 的全领域算法。由于文章中采用 C/C++ 的语法,于是就有不少读者朋友反馈语言层面就被劝退了,更何况是算法。
于是,2021 年 06 月 12 日,《光天化日学C语言》 应运而生。这个系列文章主要服务于高中生、大学生以及职场上想入坑C语言的志同道合之人,希望能给祖国引入更多编程方面的人才,并且让自己的青春不留遗憾!
这一章的主要内容是聊一聊二进制和位运算。
二、人物简介
- 第一位登场的就是今后会一直教我们C语言的老师 —— 光天。
- 第二位登场的则是今后会和大家一起学习C语言的没什么资质的小白程序猿 —— 化日。
三、再谈二进制
- 我们在学习 光天化日学C语言(06)- 进制转换入门 的时候,曾经提到过二进制。
- 在计算机中,非零即一。
1、二进制数值表示
- 例如,在计算机中,我们可以用单纯的 0 和 1 来表示数字。
1、101、1100011、100101010101 都是二进制数。
123、423424324、101020102101AF 则不是,因为有 0 和 1 以外的数字位。
- 一般为了不产生二义性,我们会在数字的右下角写上它的进制,例如:
- 101 0 ( 10 ) 1010_{(10)} 1010(10)
- 代表的是十进制下的 1010,也就是十进制下的 “一千零一十”。
- 101 0 ( 2 ) 1010_{(2)} 1010(2)
- 代表的是二进制下的 1010,也就是十进制下的 “十”。
2、二进制加法
二进制加法采用从低到高的位依次相加,当相加的和为2时,则向高位进位。
- 例如,在二进制中,加法如下: 1 ( 2 ) + 1 ( 2 ) = 1 0 ( 2 ) 1 ( 2 ) + 0 ( 2 ) = 1 ( 2 ) 0 ( 2 ) + 1 ( 2 ) = 1 ( 2 ) 0 ( 2 ) + 0 ( 2 ) = 0 ( 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)} 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 ) 1 0 ( 2 ) − 1 ( 2 ) = 1 ( 2 ) 0 ( 2 ) − 0 ( 2 ) = 0 ( 2 ) 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(2)−1(2)=0(2)1(2)−0(2)=1(2)10(2)−1(2)=1(2)0(2)−0(2)=0(2)
- 而我们今天要讲的位运算正是基于二进制展开的。
四、位运算简介
- 位运算可以理解成对二进制数字上的每一个位进行操作的运算。
- 位运算分为 布尔位运算符 和 移位位运算符。
- 布尔位运算符又分为 位与(&)、位或(|)、异或(^)、按位取反(~);移位位运算符分为 左移(<<) 和 右移(>>)。
- 如图所示:
- 接下来几天,每天都会更新一篇,对每个位运算符的详细解读,并且配有例题。
- 光天化日学C语言(14)- 位运算 & 的应用 (已更新)
- 光天化日学C语言(15)- 位运算 | 的应用 (待更新)
- 光天化日学C语言(16)- 位运算 ^ 的应用 (待更新)
- 光天化日学C语言(17)- 位运算 ~ 的应用 (待更新)
- 光天化日学C语言(18)- 位运算 << 的应用 (待更新)
- 光天化日学C语言(19)- 位运算 >> 的应用 (待更新)
五、位运算概览
- 今天,我们先来对位运算进行一个初步的介绍。后面会对每个运算符的应用做详细介绍,包括刷题的时候如何运用位运算来加速等等。
1、布尔位运算
- 对于布尔位运算,总共有四个,如下表所示:
C语言运算符表示 | 含义 | 示例 |
---|---|---|
& | 位与 | x & y |
| | 位或 | x | y |
^ | 异或 | x ^ y |
~ | 按位取反 | x ~ y |
1)位与
- 位与就是对操作数的每一位按照如下表格进行运算,对于每一位只有 0 或 1 两种情况,所以组合出来总共 2 2 = 4 2^2 = 4 22=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)
(1) 在C语言中,以
0b
作为前缀,表示这是一个二进制数。那么a
的实际值就是 ( 1010 ) 2 (1010)_2 (1010)2。 -
(
2
)
(2)
(2) 同样的,
b
的实际值就是 ( 0110 ) 2 (0110)_2 (0110)2; -
(
3
)
(3)
(3) 那么这里
a & b
就是对 ( 1010 ) 2 (1010)_2 (1010)2 和 ( 0110 ) 2 (0110)_2 (0110)2 的每一位做表格中的&
运算。 - 所以最后输出结果为:
2
- 因为输出的是十进制数,它的二进制表示为: ( 0010 ) 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 (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 (1100)2 。
4)按位取反
- 按位取反其实就是 0 变 1, 1 变 0。
- 同样,我们来看一段程序。
#include <stdio.h>
int main() {
int a = 0b1;
printf("%d\\n", ~a );
return 0;
}
- 这里我想卖个关子,同学们可以自己试一下运行结果。
- 至于为什么会输出这个结果,我会在 光天化日学C语言(17)- 位运算 ~ 的应用 (待更新) 中进行详细讲解,敬请期待。
2、移位位运算
- 对于移位位运算,总共有两个,如下表所示:
C语言运算符表示 | 含义 | 示例 |
---|---|---|
<< | 左移 | x << y |
>> | 右移 | x >> y |
1)左移
- 其中
x << y
代表将二进制的 x x x 的末尾添加 y y y 个零,就好比向左移动了 y y y 位。 - 比如 ( 1011 ) 2 (1011)_2 (1011)2 左移三位的结果为: ( 1011000 ) 2 (1011000)_2 (1011000)2。
2)右移
- 其中
x >> y
代表将二进制的 x x x 从右边开始截掉 y y y 个数,就好比向右移动了 y y y 位。 - 比如
(
101111
)
2
(101111)_2
(101111)2 右移三位的结果为:
(
101
)
2
(101)_2
(101)2以上是关于光天化日学C语言(13)- 位运算概览 | 开启位运算的征程的主要内容,如果未能解决你的问题,请参考以下文章
光天化日学C语言(16)- 位运算 ^ 的应用 | 最神奇的异或运算
光天化日学C语言(14)- 位运算 & 的应用 | C语言课上学不到的哦~
光天化日学C语言(18)- 位运算 << 的应用 | 左移的一些高端用法