C语言再学习 -- 位操作
一、二进制
二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。
位:"位(bit)"是电子计算机中最小的数据单位。每一位的状态只能是0或1。
字节:8个二进制位构成1个"字节(Byte)",它是存储空间的基本计量单位。1个字节可以储存1个英文字母或者半个汉字,换句话说,1个汉字占据2个字节的存储空间。
字:"字"由若干个字节构成,字的位数叫做字长,不同档次的机器有不同的字长。例如一台8位机,它的1个字就等于1个字节,字长为8位。如果是一台16位机,那么,它的1个字就由2个字节构成,字长为16位。字是计算机进行数据处理和运算的单位。 二进制没有占位符
二进制1011表示:
1x2^3 + 0x2^2 + 1x2^1 + 1x2^0 = 11
-5 二进制为 1111 1011 十进制数之间转二进制 关系是 取反加一
5的 二进制 0000 0101
取反 1111 1010
加一 1111 1011
有符号整数参看:C语言再学习 -- 负数
二进制浮点数参看:C语言再学习 -- 浮点数
二、八进制
把二进制从右向左每三个数位分成一组,每一组单独转换成十进制结果一定在0到7之间。把所有组的转换结果按顺序书写就得到数字的八进制表示方式。
例如,八进制数451(在C中写为0451)表示:
4x8^2 + 5x8^1 + 1x8^0 = 297
可以在程序中用八进制方式表示数字必须以0作为开头,采用%o作为占位符可以把一个整数的八进制表示方式打印在屏幕上
三、十六进制
把二进制数字从右向左每四个数位分成一组,每组单独转换成十进制一定在0到15之间,如果转换结果在10到15之间用英文字母a到f分别表示,把所有转换结果按顺序书写就得到数字的十六进制表示方式
例 0110 1010 转换成十六进制为 6a
例 0010 1011 43 053 2b
在程序中使用十六进制方式表示数字,必须以0x开头,采用%x或者%X作为占位符可以把数字的十六进制表示方式打印在屏幕,上打印结果中不包含0x。
%x做占位符的时候打印结果中的英文字母都是小写的
%X做占位符的时候打印结果中的英文字母都是大写的
//占位符
#include <stdio.h>
int main() {printf("0%o %d\n",0152,0152); //八进制 记得前面加个 0printf("0x%X 0x%x 0%o %d\n",0xcb,0xcb,0xcb,0xcb); // 十六进制记得前面加 0xreturn 0;
}
输出结果:
0152 106
0xCB 0xcb 0313 203
参看:C语言再学习 -- printf、scanf占位符
参看:二进制转换对照表
扩展:进制转换器
1、整数部分的二进制转换成十进制。
指数 | 十进制数 | 二进制数 |
20 | 1 | 0001 |
21 | 2 | 0010 |
22 | 4 | 0100 |
23 | 8 | 1000 |
24 | 16 | 0001 0000 |
25 | 32 | 0010 0000 |
26 | 64 | 0100 0000 |
27 | 128 | 1000 0000 |
28 | 256 | 0001 0000 0000 |
29 | 512 | 0010 0000 0000 |
210 | 1024 | 0100 0000 0000 |
211 | 2048 | 1000 0000 0000 |
212 | 4096 | 0001 0000 0000 0000 |
213 | 8192 | 0010 0000 0000 0000 |
214 | 16384 | 0100 0000 0000 0000 |
215 | 32768 | 1000 0000 0000 0000 |
216 | 65536 | 0001 0000 0000 0000 0000 |
2、小数部分的二进制转换成十进制。
记到小数点后六位就够了,如果再向后,你可以继续除2,不过这题目可就有些变态了。
指数 | 分数 | 二进制 | 十进制 |
2-1 | 1/21 | .1 | .5 |
2-2 | 1/22 | .01 | .25 |
2-3 | 1/23 | .001 | .125 |
2-4 | 1/24 | .0001 | .0625 |
2-5 | 1/25 | .0000 1 | .03125 |
2-6 | 1/26 | .0000 01 | .015625 |
3、二进制(B,Binary),八进制(O,Octal) 十进制(D,Decimalist),十六进制(H,Hex)
二进制 | 八进制 | 十进制 | 十六进制 |
0000 | 0 | 0 | 0 |
0001 | 1 | 1 | 1 |
0010 | 2 | 2 | 2 |
0011 | 3 | 3 | 3 |
0100 | 4 | 4 | 4 |
0101 | 5 | 5 | 5 |
0110 | 6 | 6 | 6 |
0111 | 7 | 7 | 7 |
1000 | 10 | 8 | 8 |
1001 | 11 | 9 | 9 |
1010 | 12 | 10 | A |
1011 | 13 | 11 | B |
1100 | 14 | 12 | C |
1101 | 15 | 13 | D |
1110 | 16 | 14 | E |
1111 | 17 | 15 | F |
四、位运算符
1、二进制反码或按位取反:~
需要确认该值是否为unsigned类型,如果是有符号则,正数为原来的数取反、加1
例如:~6
0000 0110
1111 1001 =473 = -0000 0111 ==-7
2、&(按位与)(串联)
只有对应数位上都是1的时候结果才是1
3 二进制 0000 0011
5 二进制 0000 0101
按位与 & 为 0000 0001
结果是 1
C也有一个组合的位与赋值运算符:&=。下面两个语句产生相同的最后结果:
val &= 0377;
val = val & 0377
3、|(按位或)(并联)
只要对应数位中有1则结果就是1
3 二进制 0000 0011
5 二进制 0000 0101
按位或 | 为 0000 0111
结果为 7
C也有一个组合的位或赋值运算符:|=。下面两个语句产生相同的最后结果:
val 1= 0377;
val = val | 0377
4、^(按位异或)
如果对应数位内容一样则结果是0,否则结果为1
3 二进制 0000 0011
5 二进制 0000 0101
按异或 ^ 为 0000 0110
结果位 6
C也有一个组合的位异或赋值运算符:^=。下面两个语句产生相同的最后结果:
val ^= 0377;
val = val ^0377
5、移位运算符
移动操作符可以把数字中每个二进制数位统一想左或者向右移动n个位置,移动操作会得到一个新数字,不会修改原来的数字。
1) <<表示向左移动操作
向左移动是右边空出来的位置上一定补充0
例如 二进制 (0000 0011) << 2 向左移动两位结果为 0000 1100
3 0000 0011 3 x 2^2 =12
0000 1100
再如:
-5 << 2 = -20
也可以这么理解,向左移动n位相当于乘以2的n次方。
2) >>表示向右移动操作
对于unsigned类型,右移时使用0填充左端空出的位。对于有符号类型,结果依赖于机器。空出的位可能用0填充,或者使用符号(最左端的)位的副本填充。
例如 二进制 (0000 1100) >> 2 向右移动两位结果为 0000 0011
12 0000 1100 12 / 2^2 = 3
0000 0011
也可以这么理解,相对于unsigned类型而言,向右移动n位相当于除以2的n次方
注意:
应避免使用 a << -5 这种类型的移位,因为它们的效果是不可预测的,使用类型移位的程序时不可移植的。
编译器会出现,警告: 左移次数为负 [默认启用]。
再来看看下面的例子:
0x01 << 2 + 3; 结果是多少?
#include <stdio.h>int main (void)
{printf ("%d\n", 0x01 << 2 + 3);return 0;
}
输出结果:
32
因为 "+" 号的优先级比移位运算符的优先级高。
如果再把例子改写一下:
0x01 << 2 + 30; 或者 0x01 << 2 -3; 这样行吗?
#include <stdio.h>int main (void)
{printf ("%d\n", 0x01 << 2 + 30);return 0;
}
输出结果:
警告: 左移次数大于或等于类型宽度 [默认启用]
#include <stdio.h>int main (void)
{printf ("%d\n", 0x01 << 2 - 3);return 0;
}
输出结果:
警告: 左移次数为负 [默认启用]
首先考虑的还是运算符优先级,然后看,一个整型数长度为 32 位,左移 32 位则会溢出。左移 -1 位也是不对的。
所以说,左移和右移的位数不能大于数据的长度,不能小于 0。
五、位运算符用法
1、掩码
flags &= MASK;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
flags &= 0x02;
flags = 0000 0010
这个语句将导致flags的除位 1之外,所有位都被设为 0。
2、打开位
flags |= MASK;
例如:flags二进制为 1001 0100 MASK二进制为 0000 0010 即:
flags |= 0x02;
flags = 1001 0110
这个语句将flags中的位1设为1,并保留其他所有位不变。
结合移位运算符
flags |= MASK << n;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0001 n为4即:
flags |= 0x01<<4; (高电平)
flags = 1001 1110
这个语句将flags的位 3 设为1,并保留其他所有位不变。
3、关闭位
flags &= ~MASK;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
flags &= ~0x02;
flags = 1001 0100
这个语句将flags除位1设为0以外,保留其他所有位不变。
结合移位运算符
flags &= ~(MASK << n);
例如:flags二进制为 1001 0110 MASK二进制为 0000 0001 n为3即:
flags &= ~(0x01<<3); (低电平)
flags = 1001 0010
这个语句将flags的位 2 设为0,并保留其他所有位不变
4、转置位
flags ^= MASK;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
flags ^= 0x02;
flags = 1001 0100
转置一个位表示如果该位打开,则关闭该位,如果该位关闭,则打开该位。
5、查看一位的值
if ((flags & MASK) == MASK)
puts ("Wow);
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
if ((flags & 0x02) == 0x02)
puts ("Wow);
这个语句可判断flags位1是否为1,由于位运算符的优先级低于==,因此需要在flags & MASK的两侧加上圆括号。
六、位字段
扩展:C语言中的位字段
C语言再学习 -- 位操作相关推荐
- C语言再学习 -- 详解C++/C 面试题 2
(经典)C语言测试:想成为嵌入式程序员应知道的0x10个基本问题. 参看:嵌入式程序员面试问题集锦 1.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define ...
- C语言再学习--关键字
如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/53021879 C语言一共有32个关键字,如下表所示: 关键字 说明 auto ...
- C语言再学习 -- 创建excel文件
参看:C语言操作Excel表格 上一篇文章讲了一下 cJSON,可以生成json文件了.这篇文章讲一下怎么生成excel表xsl格式文件. 注意点: 1.文件类型为 xls 或者 xlsx 2.使用f ...
- C语言再学习 -- 再论内存管理
之前有总结过内存管理,参看:C语言再学习 -- 内存管理 但现在看来,缺少示例.从新再写一篇文章,着重介绍常见内存错误.跨函数使用存储区.开始吧,再论内存管理!! 发生内存错误是件非常麻烦的事情.编译 ...
- C语言再学习 -- 详解C++/C 面试题 1
参看:<高质量C++ C编程指南>.林锐 对这篇文章记忆犹新,因为之前找工作面试的时候,遇到过一家公司就是用的这套面试题.现在就结合考查的知识点和我总结完 C 语言再学习后的深入理解,来详 ...
- C语言再学习 -- 再论数组和指针
之前有总结指针数组,但是现在看来总结的太简单了.好多重要的知识点都是一带而过的.本想在后面添加后来想想算了,还是再写一篇文章来详细介绍数组和指针这对冤家吧. 之前总结的,参看:C语言再学习 -- 数组 ...
- C语言再学习 -- 时间函数
在软件设计中经常会用到关于时间的处理,用来计算语句.函数的执行时间,这时就需要精确到毫秒甚至是微妙的时间.我们首先来介绍一下,时间单位: 时间单位还有:秒(s).毫秒(ms).微秒 (μs).纳秒(n ...
- C语言再学习 -- 关键字volatile
上周确实事情挺多的,年会.公司聚餐,一到过年就有忙不完的事分心.还好C语言再学习总结的已经差不多了,年前也不展开别的了,接下来这十几天.总结几篇典型的面试题吧. 言归正传,接下来看看关键字 volat ...
- C语言再学习 -- 关键字const
const 关键字其实我们并不陌生,之前有讲过const修饰数组和指针.现在来详细介绍这个关键字. 参看:[C/C++和指针]著名的<const的思考> 一.const 介绍 1.cons ...
最新文章
- 基础篇9-python基本数据结构-列表
- 世界首部AI创作漫画正式发表:StyleGAN神还原《铁臂阿童木》画风,继承手冢治虫衣钵...
- python中ans的用法_Python的一些用法分享
- 论文浅尝 | 基于图卷积网络的跨语言图谱实体对齐
- python函数示例_PHP closeir()函数与示例
- ubuntu配置安装KBEngine服务器
- (六)关于beetlsql版本(分支)的说明
- php基础 简书,PHP的基础(一)
- openssh漏洞升级修复
- python sorted函数
- nginx reload报错 ---nginx: [alert] kill(1668, 1) failed (3: No such process)
- 我的ROS学习之路——服务通信
- Python标准库——turtle库
- python怎么读xlsx_使用Python读取xlsx文件
- 大数据舆情监测平台_大数据舆情监测与分析平台有哪些?舆情大数据监测软件排名2020...
- js截取字符串第一个和最后一个字符
- 服务器端部署营业执照识别
- 汉字应用水平测试软件,汉字应用水平测试(HZC)试点将在11个省市进行
- java 将set转成数组,Java程序将Set转换为数组
- mysql按某个条件升序_问题描述大家都知道, MySQL 中按某字段升序排列的 SQL 为 (以 id 为例,下同):SELECT * FROM `MyTable` WHERE...