寻求更好的阅读体验,请移步 :整数在计算机中的存储 —【Mculover666的个人博客】。
用于存储整数的数据类型是整型(比如int),那么,**整数在计算机中是以怎样的二进制代码存储的呢?**本篇为你揭秘整数在计算机中的存储方式~
1. 整数在编程时的表示方式(书写方式)
整数在编程时的表示方式按照进制不同,有三种表示方式:
- 十进制:直接书写
- 十六进制:前缀0X或者0x
- 八进制:前缀0(是零不是字母O)
- 二进制:不可以,用十六进制代替
2. 为什么不直接存储整数的二进制代码
十进制的整数可以直接转化为二进制,具体见常用进制及其转化一文,对于整数的符号则用最高位来表示,这样做的优点是简单方便,但是这样做的缺点有二:
- 直接存储导致运算(减法)的时候比较复杂,不利于CPU的硬件设计,对于加法运算没有什么影响;
- 0的表示不唯一:因为最高位是符号位,所以+0(0 0000000)和-0(1 0000000)都表示0;
3. 整数以其补码存储在计算机中
3.1. 整数 -> 补码的规则
正整数的补码
- 正整数的补码:直接将正整数转化为二进制即可,位数不够左边补0。
eg.
在64位机器上,C语言的一个int占4个字节,则十进制正整数86存储在计算机中的补码是:00000000 00000000 00000000 01010110,用十六进制表示为0x00000056。
下面编写程序来验证一下:
# include <stdio.h>
int main(void)
{
int i = 86;
printf("i = %d\n", i);
printf("i = %#x\n", i);
return 0;
}
运行结果为:
负整数的补码
- 负整数的补码:首先将负整数对应的正整数转化为二进制,然后将所有位取反,再加一,位数不够左边补1。
eg.
在64位机器上,C语言的一个int占4个字节,则十进制负整数-86存储在计算机中的补码是:11111111 11111111 11111111 10101010,用十六进制表示为0xFFFFFFAA。
下面编写程序来验证一下:
# include <stdio.h>
int main(void)
{
int i = -86;
printf("i = %d\n", i);
printf("i = %#X\n", i);
return 0;
}
运行结果为:
0的补码
- 0的补码表示唯一:
0
eg.
在64位机器上,C语言的一个int占4个字节,则十进制整数0存储在计算机中的补码是:00000000 00000000 00000000 00000000,用十六进制表示为0x00000000。
3.2. 补码 -> 整数的规则
正整数补码的十进制
- 正整数的补码:最高位为0表示正整数的补码,直接转化为十进制即可。
eg.
在64位机器上,C语言的一个int占4个字节,则存储在计算机中的补码00000000 00000000 00000000 01010110,用十六进制表示为0x00000056,对应的十进制正整数为86。
下面编写程序来验证一下:
# include <stdio.h>
int main(void)
{
int i = 0x56;
printf("i = %d\n", i);
printf("i = %#x\n", i);
return 0;
}
运行结果为:
负整数补码的十进制
- 负整数的补码:最高位为1表示负整数的补码,将所有位(补全后的)全部取反,然后加一,得到对应的十进制数的绝对值,最后加上负号。
eg.
在64位机器上,C语言的一个int占4个字节,存储在计算机中的补码是11111111 11111111 11111111 10101010,用十六进制表示为0xFFFFFFAA,则对应的十进制负整数为-86
下面编写程序来验证一下:
# include <stdio.h>
int main(void)
{
int i = 0xFFFFFFAA;
printf("i = %d\n", i);
printf("i = %#X\n", i);
return 0;
}
运行结果为:
0补码的十进制
- 0的补码唯一,对应的十进制整数还是0。
4. 关于C语言中的数据类型
通过上一节的讲述,我们知道了整数是以其补码的形式存储在计算机中的,接下来我们看一个小问题:
4.1. 问题描述
同样将0x80存储在计算机中,取出来的结果却不同:
# include <stdio.h>
int main(void)
{
char i = 0x80;
unsigned char j = 0x80;
printf("i = %d\n", i);
printf("i = %#X\n", i);
printf("j = %d\n", j);
printf("j = %#X\n", j);
return 0;
}
运行结果如图:
4.2. 分析原因
这是因为同样的8位数据1000 0000存储在计算机中,但是变量的数据类型不同,所以解释的数据不同:
- char默认是有符号,
1000 0000的最高位为1,表示负数,所以将这个补码解释为负整数,即-128; - unsigned char是无符号的,所以将
1000 0000这个补码解释为正整数,即128;
5. 整数溢出
整数溢出后会从头开始计数,针对无符号整数溢出和有符号整数溢出两种情况进行分析:
- 无符号整数溢出:最高位进位,因为存储空间大小限制,超出的部分直接舍弃,所以会从0开始重新计数。
- 有符号整数溢出:数据位进位,导致符号位变为1,数据位清零,所以会从对应的最小的负数开始重新计数。
示例程序如下:
/**
* @ brief 测试整数的溢出
* @ author mculover666
* @ date 2019年6月26日14:42:59
* @ encoding GBK/GB2312
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
int i = INT_MAX;
unsigned int j = UINT_MAX;
printf("%d %d %d\n", i, i+1, i+2);
printf("%u %u %u\n", j, j+1, j+2);
system("pause");
return 0;
}
/*
在Mingw-w64编译后运行结果:
------------------------------------
2147483647 -2147483648 -2147483647
4294967295 0 1
请按任意键继续. . .
------------------------------------
*/