移位操作和二进制知识 常用的移位操作是<< 和 >> ,分别为左移和右移。我们在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往左移一位,最左边的位移掉了,最右边的移进来的位补零。变成,结果是-6;[-(1*2^2 + 0*2^1 + 1*2^0 +1) = -6] x>>1往右移一位,由于是有符号数,可能发生逻辑右移,也可能发生算术右移。大多数机器使用算术右移,变成,结果是-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最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/83577.html