原码、反码、补码及位操作符,C语言位操作
- 计算机中的所有数据均是以二进制形式存储和处理的。所谓位操作就是直接把计算机中的二进制数进行操作,无须进行数据形式的转换,故处理速度较快。
1、原码、反码和补码
- 位(bit)
- 是计算机中处理数据的最小单位,其取值只能是 0 或 1。
- 字节(Byte)
- 是计算机处理数据的基本单位,通常系统中一个字节为 8 位。即:1 Byte=8 bit。
- 为便于演示,本节表示的原码、反码及补码均默认为 8 位。
- 准确地说,数据在计算机中是以其补码形式存储和运算的。在介绍补码之前,先了解原码和反码的概念。
- 正数的原码、反码、补码均相同。
- 原码:
- 用最高位表示符号位,其余位表示数值位的编码称为原码。其中,正数的符号位为 0,负数的符号位为 1。
- 负数的反码:
- 把原码的符号位保持不变,数值位逐位取反,即可得原码的反码。
- 负数的补码:
- 在反码的基础上加 1 即得该原码的补码。
- 例如:
- +11 的原码为: 0000 1011
- +11 的反码为: 0000 1011
- +11 的补码为: 0000 1011
- -7 的原码为:1000 0111
- -7 的反码为:1111 1000
- -7 的补码为:1111 1001
- 注意,对补码再求一次补码操作就可得该补码对应的原码。
2、位操作符
- 语言中提供了 6 个基本的位操作符,如表 2 所示。
- 注意,计算机中位运算操作,均是以二进制补码形式进行的。
2.1 按位与(&)
- 只有两位同时为 1 时,结果才为 1;只要两位中有一位为 0,则结果为 0。用式子表示为:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
- 复合赋值运算符:&= 表示按位与后赋值。
- 例如,计算 20 和 9 按位与的结果,如下所示。
- 即:20&9=0。
- 应用一:使用 0x01 与一个数按位与,可获取该数对应二进制数的最低位。
- 应用二:使用 0x00 与一个数按位与,可使该数低位的一个字节清零。
- 例如,9&0x1 可求得 9 对应二进制数 0000 1001 的最低位 1。
- 【例 1】分析以下程序的功能,并输出其运行结果。
#include<stdio.h>
int main (void)
{
int n;
for(n=1;n<=20;n++)
if (0==(n&0x1))
printf("%d ",n);
printf ("\n");
return 0;
}
- 程序运行结果为:
2 4 6 8 10 12 14 16 18 20
- 程序分析:
- n&0x1 的功能是取出 n 对应补码二进制数的最低位(最右端位),如果该位为 0,则输出。二进制数 bn-1bn-2bn-3…b2b1b0。对应的十进制数 N 的表达式为:
- N=b0 X 20 + b1 X 21 + b2 X 22 + b3 X 23 + b4 X 24 + …
- 由于从上式中第二项开始的每一项都是偶数,故N是否偶数取决于 b0 是否偶数,故 b0 为 1 时是奇数,为 0 时是偶数。
2.2 按位或(丨)
- 只要两位中有一位为 1,结果为 1;只有两位同时为 0 时,结果才为 0。用式子表示为:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
- 复合赋值运算符:|= 按位或后赋值。
- 例如,计算 20 和 9 按位或的结果,如下所示。
- 即: 20 | 9 = 29。
2.3 按位异或(^)
- 当两位相同时,即同为 1 或同为 0 时,结果为 0;当两位相异时,即其中一位为 1,另一位为 0 时,结果为 1。即相同为 0,相异为 1。用式子表示为:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
- 由此可得按位异或的 6 个性质或特点如下。
- a^0=a。即0与任意数按位异或都得该数本身。
- 1 与任意二进制位按位异或都得该位取反(0 变 1,1 变 0)。
- a^a=0。即任意数与自身按位异或都得0。
- ab=ba。即满足交换律。
- (ab)c=a(bc)。即满足结合律。
- abb=a(bb)=a^0=a。
- 复合赋值运算符:^= 按位异或后赋值。
- 例如,计算 22 和 7 按位异或的结果,如下所示。
- 即:22^7=17。
- 【例 2】分析以下程序的功能。
#include<stdio.h>
int main (void)
{
int a=3,b=5;
a=a^b;
b=a^b;
a=a^b;
printf("a=%d,b=%d\n",a,b);
return 0;
}
- 运行结果:
a=5,b=3
- 程序分析:
- 本题是对按位异或的性质和特点的综合运用,由于没有使用中间变量,故在理解上存在一定的难度。
- 由于 a=a^b; 故:
- b=ab=abb=a(bb)=a0=a,即:b=3。
- a=ab=(ab)a=(ba)a=b(aa)=b0=b,即:a=5。
- 故实现了 a 与 b 的交换。
2.4 左移(<<)
- 将运算数的各二进制位均左移若干位,高位丢弃(不包含 1),低位补 0。左移时舍弃的高位不包含 1,则每左移一位,相当于该数乘以 2。
- 复合赋值运算符: <<= 左移后赋值。
- 例如,计算 10 左移两位的结果,如下所示。
- 丢弃左边高位移出去的 0,低位补 0。
- 左移一位相当于该数乘以 2,本例中左移两位,故相当于乘以 4。即:10<<2 = 10 X 2 X 2 = 40。
2.5 右移(>>)
- 将运算数的各二进制位全部右移若干位,正数左补 0,负数左补 1,右边移出的位丢弃。
- 复合赋值运算符: >>= 右移后赋值。
- 例如,计算 70 右移两位的结果,如下所示。
- 丢弃右边移出去的所有位,由于该数为正数,左边补 0。
- 右移一位相当于该数除以 2 取整,本例中右移两位,故相当于除以 4 取整。即:70>>2=70/4 = 17。
2.6 按位取反(~)
- 0 变 1,1 变 0。用式子表示为:
~0 = 1
~1 = 0
- 应用:~a+1=-a 即对任意数按位取反后加 1,得该数的相反数。
- 例如,计算 10 按位取反的结果,如下所示:
- 由于计算机中位运算均是以补码形式操作的,正数的补码是其本身,负数的补码为其反码加 1。
- 所得显然是负数的补码,对补码 1111 0101 再做一次求补操作,即可得该补码对应的原码。 求 1111 0101 补码的过程如下所示。
- 反码 1000 1010 --符号位 1 保持不变,数值位按位取反
- 补码 1000 1011 --反码加1
- 根据 (补码)补码=原码
- 故补码1111 0101对应的原码为1000 1011=-11,即:~(10)D =~(0100 0110)B补= (1111 0101)B补=-11
- 由此可见,~10+1=-11+1=-10,即满足 ~a+1=-a。
原码、反码、补码及位操作符,C语言位操作的更多相关文章
- JAVA:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题(5)
一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...
- Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题
一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...
- C语言原码反码补码与位运算.
目录: 一.机器数和真值 二.原码,反码和补码的基础概念 三.为什么要使用原码,反码和补码 四.原码,补码,反码再深入 五.数据溢出测试 六.位运算 ...
- 「C语言」原码反码补码与位运算
尽管能查到各种文献,亲自归纳出自己的体系还是更能加深对该知识的理解. 本篇文章便是在结合百度百科有关原码.反码.补码和位运算的介绍并深度借鉴了张子秋和Liquor相关文章后整理而出. 目录 ...
- java原码反码补码以及位运算
原码, 反码, 补码的基础概念和计算方法. 对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式. 1. 原码 原码就是符号位加上真值的绝对值, 即 ...
- 位移&二进制转换&原码&反码&补码
<< 左移 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零. 格式 需要移位的数字 << 移位的次数 计算过程 1. 按二进制形式把所有的数字向左 ...
- C语言基础(4)-原码,反码,补码及sizeof关键字
1. 原码 +7的原码是0000 0111 -7的原码是1000 0111 +0的原码是0000 0000 -0的原码是1000 0000 2. 反码 一个数如果值为正,那么反码和原码相同. 一个数如 ...
- 原码 & 反码 & 补码 & 详解
本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ...
- python之计算机硬件基本认知_数据单位_进制间转换_数的原码反码补码
一:计算机硬件基本认知 cpu: 中央处理器. 相当于人的大脑.运算中心,控制中心. 内存: 临时存储数据. 优点:读取速度快,缺点:容量小,造价高,断电即消失. 硬盘: 长期存储数据. ...
- C 标识符, 数据存储形式(原码,反码,补码)
一. 标识符 第一个字母必须是英文字母或下划线 二. 数据存储形式(补码存储) 最高位是符号位 ---- 0表示整数 ; 1 表示负数 1. 正数:原码 = 反码 = 补码 例子 : (10) 原码 ...
随机推荐
- 转载:利用UDEV服务解决RAC ASM存储设备名
利用UDEV服务解决RAC ASM存储设备名 本文转载自Maclean Liu :http://www.askmaclean.com/archives/utilize-udev-resolve-11g ...
- 关于学习ios开发的一些笔记
关于方法前的 + - 符号 前置加号(+)的方法为类方法,这类方法是可以直接用类名来调用的,它的作用主要是创建一个实例.相当于是静态的方法. 前置减号(-)的方法为实例方法,必须使用类的实例才可以调用 ...
- C#应用调试C++ dll的方法
最近碰到个C#应用闪退的问题,由于通讯部分调用了C++工程写的dll,下面介绍一种调试的方法. 右键 启动项目,分别配置常规和和调试即可,如下图. 常规中,输出目录设置为安装目录中dll对应的目录: ...
- 「小程序JAVA实战」 小程序wxss样式文件的使用(七)
转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-07/ 细说下微信小程序的wxss样式文件.源码:https://github.com/liming ...
- oracle查询列合并为行(listagg简单用法)
今天工作时遇见一个数据查询分组问题,就是将分组后同一组数据某一列合并为一行,因为之前很少用到,这次工作中刚好有用到,所以手痒难耐,将它记录下来. 查询sql如下: select t.province_ ...
- ubuntu主目录下的中文文件夹名改回英文
linux下经常用命令行,目录有中文输起来非常麻烦,想把他改回英文于是登录的时候选择英文发现没装英文语言环境,为这个重新装麻烦,只能再想办法 找了一下发现传话里有个用户文件夹更新,命令是xdg-use ...
- sendCloud群发邮件一点总结
1.群发时,若发送的邮件为html页面,则不能用[普通发送]然后foreach循环: 若是单纯的文本,则可以用普通发送,否则,第一封邮件成功后,后面的都是html乱码. 2.若要用html模板发送,可 ...
- Java多线程-线程的调度(让步)
线程的让步含义就是使当前运行着线程让出CPU资源,但是扔给谁不知道,仅仅是让出,线程状态回到可运行状态. 线程的让步使用Thread.yield()方法,yield()为静态方法,功能是暂停当前正在执 ...
- ROS源码解读(二)--全局路径规划
博客转载自:https://blog.csdn.net/xmy306538517/article/details/79032324 ROS中,机器人全局路径规划默认使用的是navfn包 ,move_b ...
- 专题2-通过按键玩中断\2440按键中断编程lesson2
1.程序优化 修改Makefile 把main.c里面的mmu代码复制到mmu.c并修改如下 main.c的修改 由于在bootloader当中一般不会使用MMU,所以 main.c 加入led.c文 ...