谈谈C语言中位运算你要知道的那些事儿
一、概念说明
1.概念
先来看一下位运算的概念:
1.1位运算
位运算简单来说,就是按二进制位进行运算。
位运算: 从现代计算机中所有的数据二进制的形式存储在设备中。即 0、1 两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算。
了解了位运算之后,我们来看一下位运算符
1.2位运算符
符号 | 描述 | 运算规则 |
---|---|---|
& | 按位与 | 两个位都为1时,结果才为1 |
| | 按位或 | 两个位都为0时,结果才为0 |
^ | 按位异或 | 两个位相同为0,相异为1 |
~ | 按位取反 | 0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位去掉,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,编译器不同,处理方法不同 |
关于右移:不同的编译器处理方法可能会不一样,有的会补符号位,有的会补0。
★小提示:
a.逻辑位运算都是以 (bit)为单位。
b.位运算符的操作数必须是整数/字符类型。
2.举例及补充
2.1位运算
以+为例
举一个简单的例子来看下( + - * \)位运算:
int a = 3; int b = 4; int c = a + b;
计算两个数的和,因为在计算机中都是以二进制来进行运算,所以上面我们所给的 int 变量会在机器内部先转换为二进制在进行相加:
3(a): 0 0 0 0 0 0 1 1
加上(+)
4(b): 0 0 0 0 0 1 0 0
等于(=)
7(c ): 0 0 0 0 0 1 1 1
通过观察我们可以发现,相比在代码中直接使用(+、-、*、/)运算符,如果有位运算符的话,代码运行效率会不会更高,随着位运算符后续的出现,发现其实确实是这样。
下面一起来看一下位运算符:
2.2位运算符
关于每个运算符举一个简单的例子,来加深理解。
2.2.1按位与“&”
运算规则:
0 & 0 = 0
0 & 1 =0
1 & 0 = 0
1 & 1 = 1
简要口诀:(同1为1,其余为0)
例如:
3 & 5
0000 0011(十进制:3)
&
0000 0101(十进制:5)
=
0000 0001 (十进制:1)
因此结果等于1(十进制)
2.2.2按位或“|”
运算规则:0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
简要口诀:同0为0,其余为1
例如:
3 | 5
0000 0011(十进制:3)
|
0000 0101(十进制:5)
=
0000 0111(十进制:7)
因此结果等于7(十进制)
2.2.3按位异或“^”
运算规则:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
简要口诀:相同为0,不同为1
例如:
4 ^ 7
0000 0100(十进制:4)
^
0000 0111 (十进制:7)
=
0000 0011(十进制:3)
因此结果等于3(十进制)
2.2.4按位非(取反)“~”
运算规则:
~1 = 0
~0 = 1
简要口诀:1变0,0变1
例如:
~15
~0000 1111(十进制:~15)
=1111 0000(十进制:240)
因此结果等于240(十进制)
2.2.5左移“<<”
补充:若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
例如:
1 << 2
即 1左移两位
0000 0001(十进制:1)
左移两位(<<2)后:
0000 0100(十进制:4)
结果为:4
2.2.6右移“>>”
补充: 操作数每右移一位,相当于该数除以2。
例如:
8 >> 2
即 8右移两位
0000 1000(十进制:8)
右移两位( >>2 )后:
0000 0010(十进制:2)
结果为:2
了解了这些概念之后,我们一起来看一下问题吧!
二、问题实战
自己编写了个题,仅用于学习,目的是为了加深对位运算的理解。
大家可以尝试实现一下
1.问题描述(开放题)
Problem Description
自己设计程序,要求用六种位运算符实现对两个整数的运算。
2.输入输出
Input
无
Output
两个整数经六种位运算分别得到的结果
三、源码实现(+详细注释)
1.注释版
//编码及注释:Code_流苏 //定义头文件 #include<stdio.h> int main() { //给定两个整数a和b 分别初始赋值为3和5 //定义d e f g h i分别存储各种位运算后的值 unsigned char a=3,b=5,c,d,e,f,g,h,i; // a(3): 0000 0011 // b(5): 0000 0101 //按位与 & c=a&b; //经过按位与运算,得到c的值为0000 0001 //以十进制输出 printf("经过按位与运算后,可得c的值:%d\n",c);//输出结果为1 //按位或 | a=3; b=5; d=a|b; //经过按位或运算,得到c的值为0000 0111 //以十进制输出 printf("经过按位或运算后,可得d的值:%d\n",d);//输出结果为7 //按位异或 ^ a=3; b=5; e=a^b; //经过按位异或运算,得到c的值为0000 0110 //以十进制输出 printf("经过按位异或运算后,可得e的值:%d\n",e);//输出结果为6 //按位非(取反) ~ a=3; b=7; //0000 0111 此处重新赋值 排除偶然性 f=~a; g=~b; //经过按位非(取反)运算,得到f的值为1111 1100 g的值为1111 1000 //以十进制输出 printf("经过按位非运算后,可得f和g的值:%d %d\n",f,g);//输出结果f的值为252,g的值为248 //移位 左移:>> 右移:>> a=3; b=5; h=a<<2; i=b>>2; //经过位移运算,得到f的值为0000 1100 g的值为0000 0001 //以十进制输出 printf("经过移位运算后,可得f和g的值:%d %d\n",h,i);//输出结果h的值为12,i的值为1 return 0;//返回0,代表程序执行结束 }
关于unsigned char的解释:
unsigned char是无符号字节型,char类型变量的大小通常为1个字节(1字节=8个位),且属于整型。这就是为什么要用unsigned char的原因。
2.纯源码版
#include<stdio.h> #include<stdlib.h> int main() { unsigned char a=3,b=5,c,d,e,f,g,h,i; c=a&b; printf("经过按位与运算后,可得c的值:%d\n",c); a=3; b=5; d=a|b; printf("经过按位或运算后,可得d的值:%d\n",d); a=3; b=5; e=a^b; printf("经过按位异或运算后,可得e的值:%d\n",e); a=3; b=7; f=~a; g=~b; printf("经过按位非运算后,可得f和g的值:%d %d\n",f,g); a=3; b=5; h=a<<2; i=b>>2; printf("经过移位运算后,可得f和g的值:%d %d\n",h,i); return 0; }
四、输出结果展示
1.输出结果
经过按位与运算后,可得c的值:1
经过按位或运算后,可得d的值:7
经过按位异或运算后,可得e的值:6
经过按位非运算后,可得f和g的值:252 248
经过移位运算后,可得f和g的值:12 1--------------------------------
Process exited after 0.3508 seconds with return value 0
请按任意键继续. . .
2.输出结果(图示版)
总结
上一篇:C语言和C++的6点区别
栏 目:C代码
下一篇:C++实现LeetCode(186.翻转字符串中的单词之二)
本文标题:谈谈C语言中位运算你要知道的那些事儿
本文地址:http://www.codeinn.net/misctech/224130.html