一、二进制

二进制是计算技术中广泛采用的一种数制。二进制数据是用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语言再学习 -- 位操作相关推荐

  1. C语言再学习 -- 详解C++/C 面试题 2

    (经典)C语言测试:想成为嵌入式程序员应知道的0x10个基本问题. 参看:嵌入式程序员面试问题集锦 1.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define ...

  2. C语言再学习--关键字

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/53021879 C语言一共有32个关键字,如下表所示: 关键字 说明 auto ...

  3. C语言再学习 -- 创建excel文件

    参看:C语言操作Excel表格 上一篇文章讲了一下 cJSON,可以生成json文件了.这篇文章讲一下怎么生成excel表xsl格式文件. 注意点: 1.文件类型为 xls 或者 xlsx 2.使用f ...

  4. C语言再学习 -- 再论内存管理

    之前有总结过内存管理,参看:C语言再学习 -- 内存管理 但现在看来,缺少示例.从新再写一篇文章,着重介绍常见内存错误.跨函数使用存储区.开始吧,再论内存管理!! 发生内存错误是件非常麻烦的事情.编译 ...

  5. C语言再学习 -- 详解C++/C 面试题 1

    参看:<高质量C++ C编程指南>.林锐 对这篇文章记忆犹新,因为之前找工作面试的时候,遇到过一家公司就是用的这套面试题.现在就结合考查的知识点和我总结完 C 语言再学习后的深入理解,来详 ...

  6. C语言再学习 -- 再论数组和指针

    之前有总结指针数组,但是现在看来总结的太简单了.好多重要的知识点都是一带而过的.本想在后面添加后来想想算了,还是再写一篇文章来详细介绍数组和指针这对冤家吧. 之前总结的,参看:C语言再学习 -- 数组 ...

  7. C语言再学习 -- 时间函数

    在软件设计中经常会用到关于时间的处理,用来计算语句.函数的执行时间,这时就需要精确到毫秒甚至是微妙的时间.我们首先来介绍一下,时间单位: 时间单位还有:秒(s).毫秒(ms).微秒 (μs).纳秒(n ...

  8. C语言再学习 -- 关键字volatile

    上周确实事情挺多的,年会.公司聚餐,一到过年就有忙不完的事分心.还好C语言再学习总结的已经差不多了,年前也不展开别的了,接下来这十几天.总结几篇典型的面试题吧. 言归正传,接下来看看关键字 volat ...

  9. C语言再学习 -- 关键字const

    const 关键字其实我们并不陌生,之前有讲过const修饰数组和指针.现在来详细介绍这个关键字. 参看:[C/C++和指针]著名的<const的思考> 一.const 介绍 1.cons ...

最新文章

  1. 基础篇9-python基本数据结构-列表
  2. 世界首部AI创作漫画正式发表:StyleGAN神还原《铁臂阿童木》画风,继承手冢治虫衣钵...
  3. python中ans的用法_Python的一些用法分享
  4. 论文浅尝 | 基于图卷积网络的跨语言图谱实体对齐
  5. python函数示例_PHP closeir()函数与示例
  6. ubuntu配置安装KBEngine服务器
  7. (六)关于beetlsql版本(分支)的说明
  8. php基础 简书,PHP的基础(一)
  9. openssh漏洞升级修复
  10. python sorted函数
  11. nginx reload报错 ---nginx: [alert] kill(1668, 1) failed (3: No such process)
  12. 我的ROS学习之路——服务通信
  13. Python标准库——turtle库
  14. python怎么读xlsx_使用Python读取xlsx文件
  15. 大数据舆情监测平台_大数据舆情监测与分析平台有哪些?舆情大数据监测软件排名2020...
  16. js截取字符串第一个和最后一个字符
  17. 服务器端部署营业执照识别
  18. 汉字应用水平测试软件,汉字应用水平测试(HZC)试点将在11个省市进行
  19. java 将set转成数组,Java程序将Set转换为数组
  20. mysql按某个条件升序_问题描述大家都知道, MySQL 中按某字段升序排列的 SQL 为 (以 id 为例,下同):SELECT * FROM `MyTable` WHERE...

热门文章

  1. Laravel中构造方法中不能写return!!!
  2. 【转】如何设计动态(不定)字段的产品数据库表?
  3. Git学习笔记(0)-错误汇总
  4. '0','\0',NULL,EOF的区别
  5. Python:基础操作(2)
  6. GPU(CUDA)学习日记(十三)------ CUDA内存简介
  7. leetcode_zigzag conversion
  8. 【图像】jpg与jpeg的区别
  9. [云炬创业管理笔记]第三章打造优秀创业团队讨论1
  10. [云炬创业管理笔记]第三章测试1