原码反码补码移码的理解及C语言验证

概念

  • 原码:如果机器字长为n,那么一个数的原码就是用一个n位的二进制数,其中最高位为符号位:正数为0,负数为1,剩下的n-1位表示概数的绝对值。位数不够的用0补全。
  • 反码:反码就是在原码的基础上,符号位不变其他位按位取反。
  • 补码:补码在反码的基础上按照正常的加法运算加1。
  • 移码:移码不管正负数,将其补码的符号位取反。

总结:

  1.   正数的反码和补码都与原码相同。
  2.   负数的反码为对该数的原码除符号位外各位取反。
  3.   负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1

各自的优缺点:

  1.   原码最好理解,但是加减法不够方便,有两个零
  2.   反码解决了加减法的问题,还是有两个零
  3.     补码理解困难,但运算和表示非常方便。

数轴表示:

理论理解起来还是不够直观,用一条数轴观察一个八位机器的数值表示:

             -128                      -127                ····                 -1                          0                          1              ····            +127     

原码:     --                     1111 1111          ····            1000 0001          0000 0000          0000 0001       ····         0111 1111

                                                                                                             1000 0000

反码:      --                   1000 0000          ····           1111  1110           0000 0000         0000 0001       ····         0111 1111

                                                                                                            1111  11111

补码:1000 0000          1000 0001          ····           1111 1111            0000 0000         0000 0001       ····         0111 1111

从上面的数轴可以看出用补码表示数值非常方便,形式非常简洁:最高位为符号位,低位从小到大排列,只有一个0,还能多表示一个数。

除此之外:使用补码,可以将符号位和数值域统一处理;加法和减法也可以统一处理;补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。因此在计算机系统中,数值一律用补码来表示和存储。

C语言验证:

#include <iostream>  
#include <cstdio>  
#define INT_MIN 0x80000000
#define INT_MAX 0x7fffffff  
using namespace std;
 
int main()
{
    //32位机器最大整数,输出为:2147483647
    cout<<"32位机器整数范围"<<endl;
    cout<<(int)INT_MIN<<" -- "<<INT_MAX<<endl;
    cout<<endl;
	
    //超过int表示范围cout默认unsigned int类型输出:2147483648
    cout<<"溢出后(C++默认转换成无符号输出):"<<endl;
    cout<<"0x80000000:"<<0x80000000<<endl;
    //超过int表示范围cout默认unsigned int类型输出:2147483649
    cout<<"0x80000001:"<<0x80000001<<endl;
    cout<<endl;
    //指定输出整型,输出:-2147483648
    printf("C直接输出溢出结果:\n0x7fffffff:%d\n",0x7fffffff);
    printf("0x80000000:%d\n",0x80000000);//指定输出整型,输出:-2147483648
    //函数参数为十六进制表示的补码,输出补码对应的原码的数值为:-2147483647 
    printf("0x80000001:%d\n",0x80000001);
    //函数参数为十六进制表示的补码,输出补码对应的原码的数值为:-1	
    printf("最大负整数:0xffffffff:%d\n",0xffffffff);
	
    int b=0x0001;
    //~b是对b的补码(包括符号位)按位取反,~b,0xfffe,此补码对应的值为-2,补码0xffff对应-1 
    printf("\n0x0001:%d\n~0x0001:%d\n",b, ~b);//输出为-2
    return 0;
}

运行结果:

参考链接:  原码、反码、补码和移码其实很简单

                   计算机中原码,反码,补码之间的关系

猜你喜欢

转载自blog.csdn.net/xyj1536214199/article/details/77986089