原码,反码,补码以及作用

 

在计算机内,有符号数有3种表示法:原码、反码和补码。

原码:原码是计算机中对数字的二进制定点表示方法,最高位为符号位,符号位为1为正,符号位为0为负。

优点:简单直观

缺点:不能直接进行运算

反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。

补码:正数的补码与其原码相同;负数的补码是在其反码的末位加1

计算机中,所有的数值都是用补码来存储的。

+7原:

0

0

0

0

0

1

1

1

-7原:

1

0

0

0

0

1

1

1

 

+7反:

0

0

0

0

0

1

1

1

-7反:

1

1

1

1

1

0

0

0

 

+7补:

0

0

0

0

0

1

1

1

-7补:

1

0

0

0

1

0

0

0

 

-128特殊

-128

1

0

0

0

0

0

0

0

 

1

1

1

1

1

1

1

1

0

0

0

0

0

0

0

1

1

1

1

1

1

1

1

只有有符号的整数才有原码、反码和补码的!其他的类型一概没有。虽然我们也可以用二进制中最小的数去对应最小的负数,最大的也相对应,但是那样不科学,下面来说说科学的方法。还是说一个字节的整数,不过这次是有符号的啦,1个字节它不管怎么样还是只能表示256个数,因为有符号所以我们就把它表示成范围:-128-127。它在计算机中是怎么储存的呢?可以这样理解,用最高位表示符号位,如果是0表示正数,如果是1表示负数,剩下的7位用来储存数的绝对值的话,能表示2^7个数的绝对值,再考虑正负两种情况,2^7*2还是256个数。首先定义0在计算机中储存为00000000,对于正数我们依然可以像无符号数那样换算,从00000001到01111111依次表示1到127。那么这些数对应的二进制码就是这些数的原码。到这里很多人就会想,那负数是不是从10000001到11111111依次表示-1到-127,那你发现没有,如果这样的话那么一共就只有255个数了,因为10000000的情况没有考虑在内。实际上,10000000在计算机中表示最小的负整数,就是这里的-128,而且实际上并不是从10000001到11111111依次表示-1到-127,而是刚好相反的,从10000001到11111111依次表示-127到-1。负整数在计算机中是以补码形式储存的,补码是怎么样表示的呢,这里还要引入另一个概念——反码,所谓反码就是把负数的原码(负数的原码和和它的绝对值所对应的原码相同,简单的说就是绝对值相同的数原码相同)各个位按位取反,是1就换成0,是0就换成1,如-1的原码是00000001,和1的原码相同,那么-1的反码就是11111110,而补码就是在反码的基础上加1,即-1的补码是11111110+1=11111111,因此我们可以算出-1在计算机中是按11111111储存的。总结一下,计算机储存有符号的整数时,是用该整数的补码进行储存的,0的原码、补码都是0,正数的原码、补码可以特殊理解为相同,负数的补码是它的反码加1。

 

#include<stdio.h>

int main(void)

{

    char c=0xff;

    printf("c=%d\n", c);

 

    unsigned int d=0xffffffff;

 

    printf("d=%d\n", d);

    printf("d=%u\n", d);

 

    return 0;

}


输出结果为

c=-1

d=-1

d=4294967295

解析

char为一字节。一字节=8位。而系统默认的常量为4字节,32位。所以0xff赋值给c的时候要进行截取,截取低8位。

%d输出10进制有符号的数。

这里用16位来表示运算过程,32位一样

0xff

0

0

0

0

0

0

0

0

1

1

1

1

1

1

1

1

 

红色部分为截取的低八位11111111赋值给c

c

1

1

1

1

1

1

1

1

c的符号位为1

c为负

所以此时存储的为补码。要输出他的原值,就要反过来求原码

求原码方法。补码取反+1

c补

1

0

0

0

0

0

0

1

所以打印结果为-1

unsigned int 声明的d为无符号整形

printf(“%d\n”,d);转化成有符号数输出,同上

%u表示输出无符号的整数,十进制。0xffffffff=4294967695

 

 

类型

所占字符

字节

char

1

8

short

2

16

int

4

32

long long

8

64

 

 

#include<stdio.h>

 

 

int main(void)

{

    char a=-1;

    printf("a=0x%x\n", a);

 

    unsigned char c=-1;

    printf("c=0x%x\n", c);

 

 

    return 0;

}

输出结果为

a=0xffffffff

c=0xff

扩充

有符号数扩充时,填充符号位,符号位为0,填充0,符号位为1,填充1

无符号数扩充时,全部填充0.

溢出

#include<stdio.h>

 

int main(void)

{

    char c=-0xff;

    int d=-0xff;

 

 

    printf("c=0x%x\n", c);

    printf("d=0x%x\n", d);

 

    return 0;

}

编译是报错

4.c: In function ‘main’:

4.c:5: warning: overflow in implicit constant conversion

输出结果为:

c=0x1

d=0xffffff01

char所表示的有符号数为-128-127

而-0xff为-255.超过范围。会造成溢出。

%d表示输出十进制整数,有符号。四字节

%u表示输出十进制整数,无符号。四字节

%x表示以十六进制输出数值在电脑内存中所表示的方法。四字节

 

有符号数和无符号数的运算

#include<stdio.h>

 

int main(void)

{

    unsigned int a=10;

 

    if( (a+(-60))>10 )

    {

        printf("(10+(-60))>10\n");

    }

 

    unsigned int b=1;

    if( b<-1 )

    {

        printf("1<-1\n");

    }

 

    return 0;

}

输出结果为:

(10+(-60))>10

1<-1

解析:

当无符号数和有符号数进行运算时。有符号数自动转换为无符号数,隐式转换。

此例中-60进行隐式转换。转换为一个非常大的正数。

同理, -1也会转换为一个非常大的正数。

用%u输出结果会得到

10+(-60)=4294967246

-1=4294967295

所以下面的条件才会成立

 

问题:

#include<stdio.h>

 

int main(void)

{

    unsigned char a=1;

 

    if(a<-1)

    {

        printf("1<-1\n");

    }

 

    return 0;

}

输出结果为空

why?

a转换为int类型的为1

1<-1?显然不成立。

总而言之。计算机中数值的各种元素是建立在补码的基础上的,理解了补码,这些问题不难解答。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值