NG编程论坛_免费编程教程_零基础轻松学编程_做下一个技术大神!

 找回密码
 加入NG

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

查看: 166|回复: 0

[转载] int类型在内存中的存储方式

[复制链接] [提交至百度]

  离线 

新浪微博达人勋


扫一扫,手机继续看本帖!
已在线3天16小时40分
发表于 2017-1-6 21:38:29 | 显示全部楼层 |阅读模式

立即注册NG,提升编程能力,成为下一个神!

您需要 登录 才可以下载或查看,没有帐号?加入NG 新浪微博登陆

x
Q1:int类型在内存中是以何种方式存储的?
要解决这个问题,我们需要首先比较深入地理解下int类型。
本文中的int类型的相关数据都以32位操作系统下的VC++6.0编译器环境为准。在下表中可以看到,int类型表示带有符号的整型,而unsigned int类型为无符号的整型。
类型名称
占字节数
取值范围
int
4B
-2^31~2^31-1
unsigned int
4B
0 ~ 2^32

1、占用的比特位数量
在32位操作系统下,两者都是占用4个字节,每个字节有8个比特位,因此有32个0-1的二进制位数。两者的不同在于,int类型有正负号(±)的存在,需要比unsigned int类型多消耗一个位数。
2、符号的表示方法
      在所有被int类型占用的比特位中,左起第一个位就是符号位。int类型的符号位上,0表示正数,1表示负数。在32位操作系统下,其余后面31位是数值位。
3、数字0的表示方法
      按照上面提到的符号,我们有了两种0的表示方法,即“+0”和“-0”。
      实际上,在32位系统下int类型中,我们计算机已经强行规定了这种情况,数字0采用“+0”的表示方法,即00000000 00000000 00000000;而“-0”这个特殊的数字被定义为了-2^31。
      因此我们看到32位系统下int类型的取值范围中,负数部分比正数部分多了一个数字,正数的最大取值是2^31-1,而负数的最小取值是-2^31。正数部分之所以要减去1,是因为被数字0占用了,而负数部分不需要用来表示0,因此原本的“-0”就用来表示-2^31这个数字。
那么是不是实现了上面已经提到的int类型的深入理解,我们就可以知道内存中int类型的数据表达了呢?
比如int类型的数字“-1”,按照上面的理解方式,在内存中32个比特位上应该是这样子的:10000000 00000000 00000001,左边第一个1表示负号,后面31位表示数值部分“1”。实际情况并不是这样。这里就需要引入“补码”这个概念了。
Q2:什么是“补码”?
     要回到这个问题,得额外补充两个概念,“原码”和“反码”。
      计算机中的符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。
1、原码(true form)
      原码,是计算机中一种对数字的二进制定点表示方法。原码表示法在数值前面前面有一位符号位(即最高位为符号位),正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
      怎么样,是不是觉得眼熟,没错!Q1中结尾提到的int类型数值“-1”的32位二进制就是原码,即10000000 00000000 00000001。与之对应的,正数“+1”就是00000000 00000000 00000001。
      那么为何不用原码在内存中表示数值呢?
我们举个例子(以8位二进制表示)
十进制
原码
1
0000 0001
-1
1000 0001
结果(原码)
1000 0010
结果(十进制)
-2
上述结果换算成十进制为-2,这显然出错了。这是由于计算机在计算时以加法进行计算的算法更简便,减法先转换为负数,再进行加法运算。因此,原码的符号位不能直接参与运算。
总结:原码是有符号数的最简单的编码方式,便于输入输出,但作为代码加减运算时较为复杂,故计算机一般不采用这种编码方式存储符号数。
2、反码(ones’ complement)
    首先我们来了解下反码表示法的规定:“正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。”
      什么意思呢?举个例子说明下:
  • 对于正数和“+0”而言,其原码本身就是反码,例如 8位二进制“+1”,其原码与反码都是00000001;
  • 对于负数和“-0”而言,符号位与原码中一样,保持不变,其余位数逐位取反,1换成0,0换成1,例如 “-1”,其8位二进制原码是1000 0001,其反码是1111 1110;
那么我们是否已经可以正常进行运算了呢?
我们举个三个例子:
例一:1+2=3(以8位二进制表示)
十进制
原码
反码
1
0000 0001
0000 0001
2
0000 0010
0000 0010
结果(反码)
0000 0011
结果(原码)
0000 0011
结果(十进制)
3
计算结果正确。
例二:1+(-2)=-1
十进制
原码
反码
1
0000 0001
0000 0001
-2
1000 0010
1111 1101
结果(反码)
1111 1110
结果(原码)
1000 0001
结果(十进制)
-1
      计算结果正确。
例三:1+(-1)=0
十进制
原码
反码
1
0000 0001
0000 0001
-1
1000 0001
1111 1110
结果(反码)
1111 1111
结果(原码)
1000 0000
结果(十进制)
-0
      计算结果为-0,问题来了,由于-0的存在,使得二进制与十进制的互换不再是一一对应的关系。
      总结:由于-0这个问题的存在,会使得计算机需要增加额外的物理硬件配合运算,所以在计算机发展的早期就已经抛弃了使用反码储存数据。
3、补码
      补码正是基于反码的“-0”问题诞生的,可以解决这个问题。
    补码的计算方法是:正数和+0的补码是其本身,负数则先计算其反码,然后反码加上1,得到补码。
      补码换算为原码的过程中,如果补码是正数或者+0的补码,则其原码就是补码本身;如果补码是负数或者-0的补码,则其原码的计算方法是,先将补码减掉1,得到反码,再将反码取反,得到原码。
      以上的说法有些绕,但是补码的算法应该已经说清楚了。下面举一些例子。
例一:1+(-1)=0
十进制
原码
反码
补码
1
0000 0001
0000 0001
0000 0001
-1
1000 0001
1111 1110
1111 1111
结果(补码)
0000 0000
结果(反码)
0000 0000
结果(原码)
0000 0000
结果(十进制)
+0
计算结果正确,+0即是数字0的唯一表示。
例二:1+2=3
十进制
原码
反码
补码
1
0000 0001
0000 0001
0000 0001
2
0000 0010
0000 0010
0000 0010
结果(补码)
0000 0011
结果(反码)
0000 0011
结果(原码)
0000 0011
结果(十进制)
3
计算结果正确。
例三:1+(-2)=-1
十进制
原码
反码
补码
1
0000 0001
0000 0001
0000 0001
-2
1000 0010
1111 1101
1111 1110
结果(补码)
1111 1111
结果(反码)
1111 1110
结果(原码)
1000 0001
结果(十进制)
-1
计算结果正确。
特别地,我们加入例四:(-1)+(-127)=-128
我们知道8位二进制的符号数的取值范围是(-2^7)~(2^7-1),即-128~127。
十进制
原码
反码
补码
-1
1000 0001
1111 1110
1111 1111
-127
1111 1111
1000 0000
1000 0001
结果(补码)
1000 0000
结果(反码)
结果(原码)
结果(十进制)
-128
由于补码1000 0000具有特殊性,计算机在编写底层算法时,将其规定为该取值范围中的最小数-128,其值与(-1)+(-127)的计算结果正好符合。
补充一点,8位二进制补码1000 0000没有对应的反码和原码,其他位数的二进制补码与此类似。

通过以上两个问题Q1和Q2的回答和引申,我们已经知道int类型在内存中存储的方式,即int类型在内存中,以补码的形式存储。而且我们还知道了为何int类型的取值范围中负数的最小值的绝对值比正数的最大值大1的原因,即-2^32的补码是10000000 00000000 00000000,原本-0的位置被-2^32取代了。

怎么样,明白了吗?


来自群组: C语言学习小组[NG]

 

                                                  


楼主的其他热帖
[C/C++语言论坛] 【记录成长】教主C征途,这是记录C路途
[C/C++语言论坛] C语言制作推箱子小游戏
[C/C++语言论坛] C语言文件的打开与关闭
[C/C++语言论坛] C语言枚举类型(Enum)
[C/C++语言论坛] C语言共用体(Union)
[C/C++语言论坛] 禁止修改变量的值




上一篇:一个C语言程序的基本机构
下一篇:C语言中整数的存储形式
nextgod.com我是下一个神!
回复
【点击@我】

使用道具 举报

     
您需要登录后才可以回帖 登录 | 加入NG 新浪微博登陆

本版积分规则

快速回复 返回列表 客服中心 搜索 官方QQ群

手机版|NG监狱|NG编程论坛 ( 豫ICP备15026783号-1 ) NG已运行| |

GMT+8, 2017-9-20 05:21 PM

Powered by Discuz!&NG编程论坛

© 2015-2017 NextGod

快速回复 返回顶部 返回列表