c语言左移右移还在傻傻分不清?

一、先知

本文用到的数据类型都是char类型,也就是有符号的一个字节的数字。众说众所周知,正数最高位为0,负数最高位为1。那左移右移的补零操作,或者说左移右移又代表着什么,原码,反码,补码又跟这个有什么关系。我这里做一下笔记,记录一下此时的理解。

二、移位

1、原码、反码、补码

其实 正数和负数的移位操作 都是在 补码 的基础上来移位的。
在给出例子前,我先来说明一些概念

  • 左移:相当于 以2的n次方
  • 右移:相当于 以2的n次方

记住结论:
正数的原码、反码、补码相同。
负数的原码、反码、补码需要转换。
转换规则:
从原码到反码:原码除了符号位,其他的全部取反
eg:1000 1010 ——》 1111 0101
从反码到补码:加1
eg:1111 0101 ——》 1111 0110

2、左移

- 正数的左移

拿左移来举例:

char i = 4;//0000 0100
char j = i<<1;//0000 1000 
char z = i<<2;//0001 0000
printf("%d\n",j);//8
printf("%d\n",z);//16

可以得到左移n位就相当于乘上2的n次方

- 负数的左移

那负数的左移是否也是这样呢,我们可以试一下,用-4来验证一下左移后是否为-8

char i = -4;//1111 1100
char j = i<<1;//1111 1000 
char z = i<<2;//1111 0000
printf("%d\n",j);//-8
printf("%d\n",z);//-16

此时有人有疑问了,为什么-4的二进制是1111 1100,按刚才的说法,不是最高为1就是负数了嘛,那不应该是1000 0100吗。
其实1000 0100是这个负数的原码,我们要从原码转换到补码我们才能进行移位运算,我们可以试一下按上面的原码到反码的操作来试一下。
1000 0100 原码
1111 1011 反码
1111 1100 补码 -4

我们可以得到-4对应的补码,然后再进行移位操作。
也就是说我们也可以通过-8的补码来获得-8的原码,也就是一开始你们认为的0000 1000
1111 1000 补码 -8
1111 0111 反码
(刚刚从反码到补码是+1,那我们这次反过来,要 -1)
1000 1000原码
(同样的,除了符号位,其余取反)

以上解释了补码的作用,以及原码补码之间的转换,以及左移的意义。

3、右移

关于右移也是相同的道理,只是在右移后,unsigned char 和 char 的补位操作有不同。
如 char 数据类型他补位是补符号位
eg:
1110 0000(-32) >> 1 等于 1111 0000(-16)
由于是负数,故右移后补的1
具体其他的数大家可以用我下面的代码来尝试

#include <stdio.h>


/*
    funtion: 将十进制输出为二进制
    para:传入参数为一个char类型的10进制数
    return:(void)
*/
void Dec_to_Bin(char dec_num)
{
    int i;
    printf("dec: %d \n",dec_num);
    printf("bin: ");
    for(i=7;i>=0;i--)
    {
        printf("%d",(dec_num & (1 << i)) ? 1 : 0);
    }
    printf("\n");
}

int main(int argc,char ** argv)
{
    Dec_to_Bin(-16);
    Dec_to_Bin(-32);
    return 0;
}

上面是我自己临时编写的十进制输出二进制函数,大家可以用这个来加深印象。
b站up主对移位操作符的讲解
以上是我在b站看的一个视频。里面有我这次说的东西,代码是我自己的,大家可以直接复制运行。up主里面还讲有关右移操作符导致的死循环问题,这里也不再赘述,有需要的可以自行观看视频。
如果这篇文章对你有帮助,点个赞,或者留下你的看法交流。本人也是小白,有什么错误也往指出。

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值