深入理解原码、反码、补码(结合C语言)

一、引出问题

在学习C语言单目操作符中~按位取反的过程中,对这样一段代码的结果产生了疑惑:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main() {
    int a = 0;
    int b = ~a;·//按位取反
    printf("%d\n", b);
    return 0;
}

输出结果:
-1

首先,int整型占4个字节,0化为二进制形式为00000000 00000000 00000000 00000000这样,按位取反后是11111111 11111111 11111111 11111111,化为十进制不应该是一个很大的负数吗,而输出结果却为-1。

之后我查阅资料才发现,我忘记了负数在计算机内存中是以补码的方式存储和进行运算的。于是我又将原码、反码、补码相关的知识复习了一遍,温故而知新,重新总结如下。

二、深入理解原码、反码、补码

在计算机中,数字的二进制位的第一位是符号位,0为正,1为负

首先要明白,原码、反码、补码是计算机用于表示带符号整数的三种编码方式

  1. 原码:原码最高位为符号位,其余位为数值绝对值的二进制值,如5的原码是0000 0101,-5的原码是1000 0110。原码表示最直观,但在进行加减法运算时存在问题,如5+(-5)理论上等于0,但原码相加得1000 1011并不是0000 0000
  2. 反码:正数的反码与原码相同,负数的反码是将原码符号位不变,其余位按位取反。如5的反码即原码0000 0101,-5的反码为1111 1010。
    引入反码是为了更好的解决二进制正数与负数间的加减法问题,如5+(-6)即0000 0101 + 1111 1001 = 1111 1110(反码),转为原码即符号位不变,其余位取反,得1000 0001,正好是-1。
    但反码仍然存在溢出和零的表示问题,如-5+6,即1111 1010 + 0000 0110 => 溢出得0;-5+5即1111 1010 + 0000 0101 = 1111 1111(反码),转为原码即1000 0000,这就与0000 0000的0的原码表示方式存在冲突,一个数总不能有两种表示方法吧。于是就有了下面的补码。
  3. 补码:正数的补码与原码相同,负数的补码是将负数的原码符号位不变,其余位取反后再加1(即负数的反码+1)。如5的补码即原码0000 0101,-5的补码为1111 1011。
    补码的引用很好的解决了加减法和0的表示问题,还能够自然地处理溢出,下面验证一下:
    • -6+5,即1111 1010 + 0000 0101 = 1111 1111,转为原码(补码-1,符号位不变,其余位取反)得1000 0001,即-1,没毛病。
    • -5+6,即1111 1011 + 0000 0110 => 溢出且得0000 0001,正数,即原码本身,得1,没毛病。
    • -5+5,即1111 1011 + 0000 0101 => 溢出且得0000 0000,与0的原码表示相同,没毛病。
      由此可见,在计算机中,补码是最常见和最有效的带符号整数表示方式。
      因此,在计算机中,带符号的整数在内存中存储的是其二进制的补码

那么这就可以理解结果为什么为-1而不是一个很大很大的负数,以上代码的计算过程如下:

//a=0的补码(也是原码)
00000000 00000000 00000000 00000000
//~取反运算得到b的补码
11111111 11111111 11111111 11111111
//补码-1
11111111 11111111 11111111 11111110
//符号位不变,按位取反得到原码
10000000 00000000 00000000 00000001

即得到打印出来的结果为-1

终于,破案了~

三、关于原码、反码、补码之间的转换

1.对于正数,原码 = 反码 = 补码
2.对于负数,此图足以:
请添加图片描述

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俗人不俗鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值