欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > 整数和浮点数在内存中存储

整数和浮点数在内存中存储

2024/10/23 21:39:16 来源:https://blog.csdn.net/weixin_62168696/article/details/143082591  浏览:    关键词:整数和浮点数在内存中存储

文章目录

  • 前言
  • 一、整型数据在内存中的存储
  • 二、大小端字节序和字节序的判断
    • 1、什么叫大小端字节序?
    • 2、为什么要存在大小端字节序存储?
    • 3、练习
  • 三、浮点型数据在内存中的存储
    • 1、浮点型在内存中的存储
    • 2、浮点数的取出
    • 4、例题


前言

人与人之间能够沟通是靠着语言进行沟通,人与机器也能进行沟通,人与机器沟通靠的也是语言。
像人与人之间可以靠汉语,英语,意大利语,日语等多种语言进行过沟通;
而人与机器沟通的语言也有很多种,像c语言,jave语言,python语言也是多种多样的。
这些语言是通过编译器转换成计算机能读懂的语言,但是计算机能够读懂的就是二进制,这些语言就是通过一些编译软件转换成二进制的形式然后说给计算机听的。那么整型类型,浮点型的数据在计算机中是如何存储的呢?让小编好好说道说道。


提示:以下是本篇文章正文内容,下面案例可供参考

一、整型数据在内存中的存储

整型数据在内存中转换成二进制的形式进行存储的,而整型数据存储进二进制的时候由两部分组成:符号位和数值位。符号位中0表示正数,1表示负数,例如下面小编画图所示:

正整数10

在这里插入图片描述

负整数10

在这里插入图片描述

在小编所写的详解操作符中小编就写过:整数的二进制在内存中在内存中有三种表现形式:原码、反码、补码。

其中正整数的原码、反码、补码都相同
对于负整数而言三种表现方法如下情况:

  • 原码:将负整数转换成二进制的形式存储在内存中,最高位为符号位。
  • 反码:将原码的二进制位除了符号位以外的数值位按位取反得到反码。
  • 补码:反码加1得到补码。

而整数在计算机中存储的则是补码的形式。为什么是补码的形式呢?
在计算机系统中,数值一律用补码来表示和存储
原因在于,是用补码,可以将符号位和数值域统⼀处理;

  1. 在计算机系统中,采用补码形式可以确保0有唯一的表示方式,无论是正0还是负0,在补码表示中都是相同的(即全0)。这避免了原码和反码表示中可能出现的+0和-0区分问题,从而简化了计算机的结构设计和运算规则。
  2. 补码表示法使得加减运算可以统一处理,即将减法运算转换为加法运算。这是因为补码具有一个特性:对一个整数的补码再求补码,等于该整数自身。因此,在计算机中,可以通过将减数取补码后与被减数相加来实现减法运算,从而简化了运算器的线路设计。此外,补码表示法还使得符号位能与有效值部分一起参加运算,进一步提高了运算速度。
  3. 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是
    相同的,不需要额外的硬件电路。

二、大小端字节序和字节序的判断

在讲解这个内容前,小编先调试一个代码让各位读者看一下:

在这里插入图片描述
在这里调试代码的时候,我们可以发现,整形变量x在内存中存储的时候是44 33 22 11,是以字节为单位倒着进行存储的,这是为什么呢?这就涉及到了大小端字节序的内容了。

1、什么叫大小端字节序?

字节序的概念

  • 在C语言等编程语言中,不同的数据类型占用的字节数不同,例如short类型通常占用2个字节,int类型占用4个字节。
  • 对于大于一个字节的数据类型,需要确定这些字节在内存中的存储顺序,即字节序。

大小端字节序

在内存中,我们把超过一个字节的数据内容进行存储的时候,就会存在存储顺序的不同,按照存储顺序的不同我们可以把它分为大端字节序存储和小端字节序存储。

  • 大端字节序存储:将一个数据的低位字节内容保存在内存的高地址处;而数据的高位字节内容保存在内存的低地址处。
  • 例如,对于一个32位的整数0x12345678,在大端字节序中,它在内存中的存储顺序会是12 34 56 78(从低地址到高地址)。

  • 小端字节序存储:将一个数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容保存在内存的高地址处。
  • 例如,对于一个32位的整数0x12345678,在小端字节序中,它在内存中的存储顺序会是78 56 34 12(从低地址到高地址)。

2、为什么要存在大小端字节序存储?

  1. 计算机内存是以字节为单位进行访问的,每个字节都有一个唯一的内存地址。
  2. 当处理大于一个字节的数据类型(如short、int、long等)时,就涉及到了如何将这些多字节数据在内存中排列的问题。因此就导致了大端字节序存储和小端字节序存储了。
  3. 不同的计算机架构可能采用不同的字节序,这是由硬件设计和处理器指令集决定的。在vs中我们字节的存储顺序就是小端字节序存储。
  4. 大小端字节序的存在使得不同的计算机系统能够根据自己的特点和需求选择合适的存储方式

3、练习

题目1
请简述⼤端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)-百度笔
试题。
答案
大端字节序和小端字节序的概念小编在这里不加赘述了。
代码段:

int check()
{int i = 1;char* p = (char*)&i;return *p;
}
int main()
{int ret = check();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}

解析:
在这里我们在判断大小端函数中定义了一个整型变量1,整型变量1在内存中按照16进制存储为0x00 00 00 01;
如果当前机器为小端字节序存储的话,则是:01 00 00 00;
如果当前机器为大端字节序存储的话,则是:00 00 00 01;
所以我们只需要取出它的第一个字节内容即可判断该机器的大小端字节序。于是我们取出整型变量的地址,强制类型转换为char*类型的并存储在字符指针变量p中,此时通过解引用p就可以得到一个字节的内容了。

题目2

#include <stdio.h>
int main()
{char a= -1;signed char b=-1;unsigned char c=-1;printf("a=%d,b=%d,c=%d",a,b,c);return 0;
}

解析:
unsigned char代表无符号字符的意思,signed代表有符号字符的意思,而char在vs中则等同于有符号。
因为字符型变量大小为1个字节。我们要将整型变量的-1存入字符型变量a中,此时发生截断。
整型变量-1在内存中的存储为补码:
在这里插入图片描述

存储到字符型数据我们发生截断,保留低位内容的数据,也就是后面的11111111。然后我们再以%d形式进行打印,发生整型提升,因为这是有符号类型的数据发生整型提升,有符号类型的数据发生整型提升以符号位进行补齐,所以我们最高位看到1认为他是负数,用符号为补齐又全是1,因为是最高位为1默认为负数,负数补码以%d形式打印的是原码,得到最终结果为-1。b和a是一样的运算过程。然后我们看到c。
在这里我们c是无符号字符型的变量
存入c中的也是11111111,然后再以%d形式进行打印,因为c是无符号字符型的变量,在打印的时候系统默认他为无符号类型的数据,然后整型提升的时候全部补0,变成:00000000 00000000 00000000 11111111,打印出来结果为255。
综上:打印结果分别为-1 -1 和255。
在这里插入图片描述

题目3
下面表达式的输出结果是什么?

#include <stdio.h>
int main()
{char a[1000];int i;for (i = 0; i < 1000; i++){a[i] = -1 - i;}printf("%d", strlen(a));return 0;
}

解析:
首先在这里我们先来看一下有无符号字符型数据的范围:
有符号字符型数据由两部分组成:符号位和数值位一共占据八位。如下图:
在这里插入图片描述

所以有符号字符型数据的范围为-128~127
而无符号字符型数据只有数值位并没有符号位:也就是8位全为数值位,所以无符号整型的范围为0~255。
再来看到本道题目,strlen遇到’\0’停止,'\0’在ASCII中对应的值为0,strlen统计的是0之前的字符个数。
在题目中a[ i ]的值从-1开始减减到-128此时在减去1

在这里插入图片描述
因为字符型在数据中存储一个字节所以只会保存八位,所以-128-1在字符数据中就变成了127,然后持续减去1最后到0,此时停止计算,所以求出的字符数为128+127 = 255个字符。
在这里插入图片描述


三、浮点型数据在内存中的存储

浮点数的本质是数学中的小数,在c语言中又有单精度浮点型(float)和双精度浮点型(double)等等之分,但是c语言中浮点型数据内存是如何存储的呢?是否和整型数据在内存中的存储是一样的呢?下面让小编用一串代码打开话题吧!

int main()
{int i = 9;float* f = (float*)&i;printf("%d\n", i);printf("%f\n", *f);*f = 9.0;printf("%d\n", i);printf("%f\n", *f);return 0;
}

在这里插入图片描述
在这里经过代码运行,如果浮点型在内存中存储和整型一样,那么结果都会是一样的,但是这里打印的结果四个都不相同这是为什么呢?这就涉及到了浮点型数据在内存中存储的问题了。

1、浮点型在内存中的存储

根据IEEE 754标准,任意一个二进制浮点数v可以表现出这种情况:V = (−1) ^ S ∗ M ∗ 2 ^ E

  • 符号位(S):用1位表示,当S=0时,V为正数;当S=1时,V为负数。
  • 有效数字(M):表示浮点数的有效部分,其取值范围其取值范围大于等于1且小于2(即1≤M<2,也就是M表现位1.xxxxxxxx的形式)。在计算机内部保存M时候,默认这个数的第一位总是1,因此可以被舍去,只保留后面的部分(即.xxxxxx的形式)。等到读取的时候,再把第⼀位的1加上去。这样做可以节省1位有效数字,提高精度。
  • 指数位(E):表示浮点数的指数部分,是一个无符号整数。对于32位浮点数(即float类型),E占8位;对于64位浮点数(即double类型),E占11位。由于科学计数法中的指数可以是负数,所以IEEE 754规定,存入内存E的真实值必须加上一个中间数(偏移量)。对于8位的E,中间数是127;对于11位的E,中间数是1023。
  • 而浮点型存储S、M、E存储如下:
    1. 对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M
    1. 对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

在这里插入图片描述

举例
例如我们要存放一个单精度浮点型的数据9。
9转换成二进制的形式就是:1001
按照上面浮点型在内存中的存储规则:V = (−1) ^ S ∗ M ∗ 2 ^ E。
此时9是正数,即s = 0;有效数字M = 1≤M<2,所以M = 1.001 ,E = 3,因为1001变成1.001向右偏移了三位。
所以9存在内存中就是0 1000 0010 00100000000000000000000;中间8位存储真实值E要变成指数形式E要加上中间数,这里是单精度浮点型即加上127得到130转换成二进制形式位1000 0010。

2、浮点数的取出

浮点数的取出正好与浮点数的存进是相同的。

  1. 取出S的值确定浮点数的正负
  2. 取出M的值再加上舍去的1得到M的值。
  3. 指数E的取出则分为三种情况:

E不全为0或不全为1

此时E的取出按照上面浮点型数据存进的规则相反,即指数E的值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

比如浮点型数据9:0 1000 0010 001000000000000000000,取出指数E的值1000 0010转换成二进制得到130,130再减去127得到3,此时E的真实值为3,然后再取出M的值0.001再加上1得到1.001*E^3 = 1001。

E全为0
在上面我们讲述了指数E存入内存中要加一个中间数,假设这是一个float型的数据(32个字节),E全为0的情况说明真实值E+127 = 0,此时真实值E = -127,此时E的值是一个非常小的数字,总体的浮点型数据无限接近于0,此时浮点型整数E的值1-127(1-1023)为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxxxx的形式。这样做是为了表示0以及无限接近于0的值。

例如:
0 00000000 10000000000000000000000表示为浮点型因该为:V = (-1)^ 0 ✖ 1.00000 ✖ 2^-127
这是E全为0的情况,浮点数无限接近于0为了表示我们因该写为:V = (-1)^ 0 ✖ 0.00000 ✖ 2^(1-127)

E全为1
当E全为1的情况此时,指数E的值为1111 1111 = 255,再减去一个中间值127得到真实值E为127。此时浮点数的值为一个非常大的值,这时,如果有效数字M全为0,表⽰±⽆穷大(正负取决于符号位s);

4、例题

此时在拿到上面代码我们进行分析:

在这里插入图片描述
整型变量9存入内存中存储转换成二进制因该为:
00000000 00000000 00000000 00001001
正常以%d形式进行打印此时打印的还是整数9;
而以浮点型形式进行打印,此时s = 0,E的指数形式 全 0 --> 按照规则E的真实值为1-127,M = 0.00000000000000000001001,因为以浮点型类型数据打印,此时打印只保留小数点后六位,全为0,即输出结果为:0.000000。
代码继续运行下去此时通过指针f对i的空间内的值进行修改,存入浮点型数据9.0,此时按照浮点型数据进行存储,S=0,E为3,M为1.001,E存入内存中要加上一个中间值,此时E的指数形式为130转换为二进制位1000 0010,M存入内存中舍去最开始的1,存入数据中的值问0.001,最终存入为:0 10000010 00100000000000000000000,以%d形式进行打印默认为整型存储此时打开计算器二进制对应的十进制为下图:
在这里插入图片描述
浮点数以%f形式打印取出规则如上面,最终结果为9.000000。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com