前言
我们现在学习一下C语言中移位操作符的使用,与原码、补码、反码的概念与使用,在原码补码反码中,正整数三个都相同,负数的话我们在下面详细讲解。
原码反码补码的概念:他们是整数的二进制表示的三种方式
正整数
在正整数中,原码反码补码都相同,我们只需要知道正整数的原码,那么它的反码和补码都是一样的,我们以7为例
原码:00000000 00000000 00000000 00000111
反码:00000000 00000000 00000000 00000111
补码:00000000 00000000 00000000 00000111
负数
我们以-7为例(方便与上面对比)
我们先写出它的原码:
原码:10000000 00000000 00000000 00000111
这里要注意啦,在原码反码补码中,第一位是符号位,它表示数字的正负,在原码反码补码中,不参与0-1之间的运算。
反码:11111111 11111111 11111111 11111000
负数的反码是在原码的基础上,符号位不变,其他位按位取反。
补码:11111111 11111111 11111111 11111001
负数的补码是在反码的基础上加上1。
这些表示方法在计算机内部处理整数时尤为重要。尤其对于补码来说。
移位操作符
移位操作符分为左移操作符"<<"和右移操作符">>",它们两个在运算的过程中也是有所区别的。
大家看到这里想必心中已经有所猜测,我们在学习移位操作符的时候为什么要先学习原码反码补码呢,它们之间是不是有什么联系,对的,你没有猜错。
位移操作符移动的时候,移动的是内存中存放的二进制补码。
左移操作符<<
还是以7为例
00000000 00000000 00000000 00000111,我们将7<<1(7左移一位)得到
00000000 00000000 00000000 00001110,左移操作符的运算规则是:左边丢弃,右边补0,在左移操作符位移之后,有*2的效果,比如我们将7左移一位之后得到十进制数为14,这是7的两倍。再左移一位之后得到:00000000 00000000 00000000 00011100,十进制值为28验证了我们的结论。
我们来看看如果是负数怎么左移的,
我们先计算出-7的补码:
11111111 11111111 11111111 11111001
之后我们对补码进行左移操作,在末位补0,左边丢弃,之后得到:
11111111 11111111 11111111 11110010
我们来看看结果是否正确,我们将操作后的补码返回为原码,首先将其变为反码(给末位减一)
11111111 11111111 11111111 11110001
之后将反码转换为原码:符号位不变,其他位按位取反
10000000 00000000 00000000 00001110
得到结果为-14,与我们预想结果一致,计算正确。
但是还有一个情况,我们使用移位操作符时,不能对小数进行运算。不然会报错。
右移操作符>>
在右移操作符中,分为两种移位方式:算术移位与逻辑移位
在算术移位中,移位规则是:右边丢弃,左边补原符号位。
在逻辑移位中,移位规则是:右边丢弃,左边补0。
还是以7为例,我们看看算术移位与逻辑移位
00000000 00000000 00000000 00000111,右移后得到:
00000000 00000000 00000000 00000011,结果为3。
在正整数中算术移位与逻辑移位结果是一样的,我们如果想要测试在编译器中使用的是算术移位还是逻辑移位我们使用负数测试
以-7为例
11111111 11111111 11111111 11111001
算术右移:
11111111 11111111 11111111 11111100,我们运算一下,看看结果,反码为:
11111111 11111111 11111111 11111011,原码为:
10000000 00000000 00000000 00000100,得到结果为-4
我们编写代码实验一下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{int a = -7;int b = a >> 1;printf("%d\n", a);printf("%d\n", b);return 0;
}
运行结果:
实验结果证明,在我们编译器中使用的移位操作是算术移位。
当然了,我们这里大多数编译器使用的都是算术移位,逻辑移位使用的并不多,这里我们就不多做阐述。
今天就到这里喽,希望这些知识可以帮助到大家,博主略尽微博之力,一起加油!共勉!