C中char在参与运算时的类型提升和溢出行为

#include <stdio.h>

int main() {
  char a = 1;
  char b = 127;
  char c = a + b;
  printf("%d\n", c);
  return 0;
}

打印的结果是-128,具体的计算过程如下:

类型提升和相加的操作:

1、变量初始化:char a = 1;初始化为1,char b = 127;‘初始化为127;

2、类型提升:在表达式a+b中,char的 类型会被提升为int类型,因此a和b在相加之前被提升为int类型,说是提升的原因是char的取值范围是-128~127而int的取值范围是-32768~32767(另外一种的char范围0-255;int范围 -2147483648~ 2147483647在这里不讨论);

3、相加的操作: a+b = 128,128的结果要存到char类型的变量c中,然而char的范围是-128-127,这里的128显然不在这个范围中,这就发生了溢出,溢出的计算结果是-128。下面来看一下具体的溢出计算过程。

在这里需要了解计算机是如何进行计算的。

在计算机二进制中我们可以使用三种方式来表示一个数:原码、反码、补码。

原码的表示:在原码中最高位存放符号位,0为正数,1为负数,因此这里a的原码表示为0000 0001,b的原码表示为01111111;

反码的表示:正数的反码是其本身,负数的反码在其符号位不变的基础上其余各位取反比如:

补码的表示:正数的补码是其本身,负数的补码在其符号位不变的基础上其余各位取反,最后一位+1,例如:

原数原码反码补码
1000000010000000100000001
-1100000011111111011111111

知道了原码、补码、反码之后我们可以看一下为何需要引入原码、补码、反码。

8位原码计算1-1:

1-1 = 1 + (-1) = (00000001)  + (10000001) = 10000010 = -2,这么计算的结果显然是有问题

8位反码计算1-1:

1-1 = 1 + (-1) = (00000001)  + (11111110) = 11111111,反码11111111的原码是10000000,按道理来说10000000的十进制的值为-0(实际不是的哈,是-128),看起来怪怪的哈,根据原码的定义我们可以知道0的原码还可以表示为00000000,这样一个0就有了两个编码,这种的不是我们希望的,我们希望最好一个数字只有一个编码来表示

8位补码计算1-1:

1-1 = 1 + (-1) =  (00000001)  + (11111111) = 0000 0000 这样以前的-0问题就么得了。

了解了原码、反码、补码的计算之后,我们就可以来计算一下a+b了。

a  0000 0001(补码)

+

b 0111 1111(补码)

= 1000 0000

char的类型是8位的,它的最高位规定为符号位,0表示正数,1表示负数,这里计算结果的最高位是1,按照规定它是一个负数

这里我们将二进制补码1000 0000转换为反码

  1000 0000

-         1

= 0111 1111

再将反码转换为原码

0111 1111
          (取反)
1000 0000

换了一圈又回去了哈,所以可以确认它是补码的极限值了,这样我们就可以确认它的值是-128了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值