移位操作和二进制知识

常用的移位操作是<< 和 >> ,分别为左移和右移。我们在C语言中有算数移位和逻辑移位两种。

算数移位:区分符号的移位       {C语言中直接是定义char m = 3}

逻辑移位:不区分符号的移位   {C语言中用unsigned char m = 3}

算数移位和逻辑移位有什么不同,举例说明,例如:

(1)对无符号数3来说:

x<<1往左移一位,最左边的位移掉了,最右边的移进来的位补零。变成00000110,所以结果是6;[1*2^2 + 1*2^1 + 0*2^0 = 6]

x>>1往右边移一位,由于是无符号数,所以逻辑右移,最右边一位移掉,最左边移进来的位补零,变成00000001,所以结果是1。[1*2^0 = 1]

(2)对于有符号数3来说:

x<<1往左移一位,最左边的位移掉了,最右边的移进来的位补零。变成00000110,所以结果是6;

x>>1往右边移一位,由于是有符号数,可能发生逻辑右移,也可能发生算术右移,这一点,C标准并没有明确地指定是使用逻辑右移还是算术右移。但大多数的机器都使用算术右移,变成00000001,所以结果还是1。

但是请注意,这只是说大多数的机器是这样的,你敢保证自己不会碰到特殊情况吗?

(3)对于有符号数-3来说:

x<<1往左移一位,最左边的位移掉了,最右边的移进来的位补零。变成11111010,结果是-6;[-(1*2^2 + 0*2^1 + 1*2^0 +1) = -6]

x>>1往右移一位,由于是有符号数,可能发生逻辑右移,也可能发生算术右移。大多数机器使用算术右移,变成11111110,结果是-2。[-(1*2^0 +1) = -2]

总结:

左移时总是移位和补零;

右移时无符号数是移位和补零,此时称为逻辑右移;

而有符号数大多数情况下是移位和补最左边的位(也就是补最高有效位),移几位就补几位,此时称为算术右移。



补充:

1.汇编语言中的逻辑右移(SHR)是将各位依次右移指定位数,然后在左侧补0,算术右移(SAR)是将各位依次右移指定位数,然后在左侧用原符号位补齐
2.高级语言右移运算符(>>)是将一个数的二进位全部右移若干位,低位移出部分舍弃,左补0
3.高级语言右移和汇编语言中的逻辑右移功能一样,但不同于算术右移

理解有误的认知:对于有符号整型数的简单认识就是:最高位为符号位,0为正,1为负。那么剩下几位应该如何表示呢?理所当然的认为:既然是1表示为0000 0001(假设为8位整型数,下同),那么-1就应该表示为1000 0001了。

实际上在C语言里,-1的正确表示应该是1111 1111,即0xFF。因为C语言里,对整型数是采用Two’s complement表示法,而前面我的理解则是Sign-Magnitude表示法(浮点数采用该法)。在Two’s complement表示法里,1000 0001表示的是-127。

几个特殊值,比如:

正值的最大表示为0111 1111,即127。[1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 +1*2^0 = 127]

负值的最小表示为1000 0000,即-128。[-(1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 +1*2^0 + 1) = -128]

并因此带来几个有趣的现象,比如从8位有符号数转成16位有符号数的填充问题。以前想当然的是填0,但这是错的,应该是填充符号位的值。比如-1=0xFF填充符号位1就应该变成0xFFFF。而如果填充的是0,那么变成0x80FF就不对了。

Two’s complement是不对称的。一个数的正负值表示,除了最高位之外,其余位数也是不尽相同的。在C语言里,当在无符号数和有符号数之间进行转换的时候,数值的二进制序列是不会改变的,改变的只是对该序列的解读模式。比如有符号数-1转换成无符号数就变成了255,虽然其二进制表示都是0xFF。如果不理解这一点,就会出Bug。

时间: 2024-10-11 05:18:00

移位操作和二进制知识的相关文章

OIer应该知道的二进制知识

计算机使用\(2\)进制,这是众所周知的.在学习\(OI\)的过程中,\(2\)进制也显得尤为重要.有时候,细节决定成败,所以我想总结一下容易被遗忘和误解的关于\(2\)进制的知识. 1.运算符 &:与.1&1=1,1&0=0,0&0=0:(同真为真) |:或.1|1=1,1|0=1,0|0=0:(一真俱真) ^:异或.1 ^ 1=0,1 ^ 0=1, 0 ^ 0=0:(阴阳协调为好,极阴或极阳皆为坏) num>>len:将num左移len位,低位溢出舍弃,高位

关于二进制知识(编码和数字)的新手总结

看了好久的文章,终于较为清楚编码问题了,下面是总结1.中文编码常见的有:简体-->GB系列(GB2312,GB2312-80,GB10830);繁体-->BIG5;还有万国码UTF-82.UTF-8并不是编码规范,而是Unicode(===UCS,另一组相同的编码名称)的实现方式,还有UTF-16,UTF-323.Unicode最早定义了2个字节的编码(但这是数学问题,并没有规定存储和传输方式),共65535个符号,这就对应UTF-16(===UCS-2);但是这还不够,又发展出UTF-32(

理解有符号数和无符号数

负数在计算机中如何表示呢? 一种是教科书,它会告诉你:计算机用"补码"表示负数.可是有关"补码"的概念一说就得一节课,这一些我们需要在第6章中用一章的篇幅讲2进制的一切.再者,用"补码"表示负数,其实一种公式,公式的作用在于告诉你,想得问题的答案,应该如何计算.却并没有告诉你为什么用这个公式就可以和答案? 另一种是一些程序员告诉你的:用二进制数的最高位表示符号,最高位是0,表示正数,最高位是1,表示负数.这种说法本身没错,可是如果没有下文,那么它

玩蛇(Python)笔记之基础Part2

玩蛇(Python)笔记之基础Part2 一.列表 1.列表 别的语言叫数组 python牛逼非要取个不一样的名字 1 age = 23 2 name = ["biubiubiu", "jiujiujiu", 22, age] 3 # namecopy = name 4 # namecopy.pop() 5 print(name) 6 # print(namecopy) List 2.列表取值 正常index 从零开始,,取倒数加负号 倒数第一就是[-1] 3.列表

我的安全之路——Web安全篇

write in my dormitory at ??9:47:05 Friday, April 7, 2017 by giantbranch(一个当初想横跨web跟二进制的菜鸡) ----致即将毕业的自己. 这是我的安全之路系列第一篇,敬请期待第二篇:<我的安全之路--二进制与逆向篇> 总览 大一:基本都在学习学校的课程,C语言,C++,高数啊,不过分数还可以,在大一复习周还在php3小时光速入门呢 大二:web开发,大概在下学期5月份这样子开始web安全 大三:开始去参加比赛,刷题,学习各

(转)我看PhD by 王珢

我看PhD by 王垠 前段时间看了一下这些关于 PhD 的负面信息: 一个专门反对读 PhD 的 BLOG 叫“100 Reasons NOT to Go to Graduate School”(下文简称“100个理由”) 哈佛大学教授 William James 的“The PhD Octopus”(写于 1903 年) 斯坦福大学的计算机系博士 Philip Guo 写的书“The Ph.D. Grind”(描述他的 PhD 生涯) 专门讽刺 PhD 生活的系列漫画“PhD Comics”

Codeforces437 B. The Child and Set

题目类型:位运算 传送门:>Here< 题意:给出\(sum和limit\),求一个集合\(S\),其中的元素互不相同且不超过\(limit\),他们的\(lowbit\)之和等于\(sum\) 解题思路 首先我们求出\(limit\)范围内每个数的\(lowbit\),并从大到小排序.要选出一些数使其和等同于\(sum\),根据我们已有的二进制知识,肯定是先选大的,再选小的. 为什么?考虑所有的\(lowbit\)都是2的幂,也就相当于我们将\(sum\)转为二进制以后,每一个1是一个\(l

第二章 基于二进制进行权限管理的理论知识

源代码GitHub:https://github.com/ZhaoRd/Zrd_0001_AuthorityManagement 1.介绍 第一章主要是介绍了这个DEMO的来由和主要使用的技术,这章内容主要是介绍如何通过二进制的位运算进行权限控制的内容. 第一章发布之后,有不少网友.园友反映程序代码运行不起来,很感谢您们的反馈,刚刚进行了代码修复,已经同步到github,感兴趣的朋友可以加我QQ! 2.二进制的位运算以及如何进行权限判断 基于二进制的权限管理,这个内容是我在两年前接触到过的一个知

十进制负数转换为二进制、八进制、十六进制的知识分享

这篇文章主要介绍了十进制负数转换为二进制.八进制.十六进制的知识分享,需要的朋友可以参考下 程序猿们或许对二进制都不陌生,二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.但是很多人都会将二进制转换成整数,但是如何用二进制表示负数呢?有的人会说,在二进制前面加个负数符合.而计算机只能认识0 和 1,又怎么去加个额外的负数符号呢?于是我们就需要用0和1来表示负数.如果想要弄懂这个,我们需要先了解什么是二进制原码. 原码是什么 原码(true form)是一种计算机中对数