【C语言进阶】原码、反码、补码、整型提升、补码运算原理

前言:

原码、反码、补码的知识点在操作符篇中讲过,但是由于写的太分散,在这里重新整理一遍,以方便查阅。 

1、计算机在任何情况下只能识别二进制

2、计算机在底层存储数据的时候,一律存储的是二进制补码的形式

3、二进制的原码、反码、补码 

        注释:

一个二进制数是由数值位符号位组成,在符号位的0表示该数为正数,1表示该数为负数


 一、原码、反码、补码

原码:原码对应的十进制数为计算机输出结果

补码:数据都是以二进制补码的形式存储的

1、 正数(正数的原码、反码、补码不变)

整数15、在C语言中可以存放到int类型的变量中,int类型时4个字节,32个比特位。

00000000 00000000 00000000 00001111  ——15的原码

00000000 00000000 00000000 00001111  ——15的反码

00000000 00000000 00000000 00001111  ——15的补码


2、负数

负数的反码是符号位不变,其余取反

负数的补码是在反码的基础上加1

以-15为例

10000000 00000000  00000000 00001111 —— -15的原码

11111111 11111111 11111111 11110000  ——  -15的反码

11111111 11111111 11111111 11110001 —— -15的补码


 二、整型提升

整型提升:

对于在内存中所占字节小于int的数据,例如 char,short类型的数据,在进行加减时会进行隐形转换,转换成int类型的数据后再进行加减

整型提升的意义:

表达式的整形运算要在CPU的相应运算期间内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。

因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。

通用CPU是难以直接实现两个8比特字节直接相加运算。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

 实例:

#include<stdio.h>
{
    char a = 5;
    //00000000 00000000 00000000 00000101 ——5的补码,要存进a中,要发生截断
    //00000101 —— 发生截断,a中存的
    char b = 126;
    //00000000 00000000 00000000 01111110 ——126的补码,要存进b中,要发生截断
    //01111110 —— 发生截断,b中存的
    char c = a + b;
    //00000101 —— a中存的
    //01111110 —— b中存的
    整型提升a,b
    //00000000 00000000 00000000 00000101 ——a
    //00000000 00000000 00000000 01111110 ——b
    //00000000 00000000 00000000 10000011 ——(a+b)
    //10000011 ——c  发生截断
    printf("%d\n",c);//在这里也要发生整型提升,%d打印的是十进制有符号整数
    //11111111 11111111 11111111 10000011 ——c的补码
    //11111111 11111111 11111111 10000010 ——c的反码
    //10000000 00000000 00000000 01111101 ——c的原码
    return 0;
}

结果是:-125

注释:

1、整型提升前面添加的是1还是0由符号位说了算,

2、发生截断后的二进制数首位是符号位,

例如:

a+b的二进制数发生截断是  10000011,首位是1,在整型提升是32为二进制数,首位为1.

整型提升后为11111111 11111111 11111111 10000011

 补充:无符号整型提升,高位补0


三、 补码运算原理

上述的代码中的a=5,b=126,c=-125原因是什么

在这里简单说一下补码运算的原理:这里以signed char 类型为例 ,取值范围为 -128~127

 在 signed char类型中正数为0~127,在上述的轮回中,超过127后循环会到达-128,依次向下循环。所以a+b=-125。

 补码的运算:

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

int main()
{
    int c = 1 - 1;
    //在这里1-1;计算机理解为 1+(-1);
    //00000000 00000000 00000000 00000001 —— 1的补码
    //11111111 11111111 11111111 11111111 —— -1的补码
    //00000000 00000000 00000000 00000000 —— (1+(-1))的补码,在这里由第一位1+1得2向 
    //前进一位,出现33位,从低位到高位只读取32位。
}

原码到补码有一种方式

首先原码取反、再+1得到补码

 -1

10000000 00000000 00000000 00000001  原码

11111111 11111111 11111111 11111110   反码

11111111 11111111 11111111 11111111    补码 

 补码到原码 有两种方式

1、首先补码-1、再取反得到原码

2、首先补码取反、再+1得到原码

以-1为例:

11111111 11111111 11111111 11111111    补码 

10000000 00000000 00000000 00000000

10000000 00000000 00000000 00000001  原码

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值