目录
前言
今天仅仅以int类型为例,讲解整型的原码、反码和补码,下周更新浮点型在计算机中的储存。
原码、反码和补码
计算机中的整数有三种2进制表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而
正数的原、反、补码都相同。
负数的原码、反码和补码:
原码:将数字按照正负的形式转换为二进制即可得到原码。
反码:将原码除符号位全取反,即可得到反码。
补码:反码加一即可得到补码。
接下来让我们从代码的角度理解上面这段话:
#include<stdio.h>
int main()
{
int a = 5;
int b = -3;
//正数5的原码、反码和补码
//00000000000000000000000000000101(正数原码)
//00000000000000000000000000000101(正数反码)
//00000000000000000000000000000101(正数补码)
//
//
//负数-3的原码、反码和补码
//10000000000000000000000000000011(负数原码)
//11111111111111111111111111111100(负数反码,将原码除符号位全取反,即可得到反码)
//11111111111111111111111111111101(负数补码,反码加一即可得到补码)
//最高位为符号位不变
//
//
printf("%.8x\n", a);
printf("%x\n", b);
return 0;
}
在代码的注释中我们可以了解数字的原码、反码和补码的计算,在计算机中数字以补码的形式储存,我们可以把数字打印出来印证一下这个结论。
从图中我们可以看到b的十六进制表达为FFFF FFFD转换为二进制为11111111111111111111111111111101,正好为b的补码。
至于为什么在计算机中储存需要用补码,我也不能很好地回答,让我们从一个比较小角度来解读。让我们来比较一下5和-3的补码:
将两者相加,可以直接得到2的补码,通过补码可以顺利解决正数和负数的加法。
整形提升
C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
我们来看看,整形提升是怎么发生并且影响我们的程序的。
整形提升是按照变量的数据类型的符号位来提升的,这里的类型指的是提升之前的整形。
发生整形提升的实例1
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
{
//a = 0xb6 = 10110110
//整形提升之后11111111111111111111111110110110变为负数
printf("a");
}
if (b == 0xb600)
{
//b = 0xb6 = 1011011000000000
//整形提升之后11111111111111111011011000000000变为负数
printf("b");
}
if (c == 0xb6000000)
{
//c是int类型,不发生整形提升
printf("c");
}
return 0;
}
最后输出的结果只有c:
发生整形提升的实例2
int main()
{
char c = 1;
//不发生整形提升
printf("%u\n", sizeof(c));
//发生整形提升
printf("%u\n", sizeof(+c));
//发生整形提升
printf("%u\n", sizeof(-c));
return 0;
}
整形提升结论
字符和短整型只要被操作,都发生整形提升。
算数转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。(向上转换)