IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> [C语言数据存储深度解析]-内存数据搞不懂?三千字长文带你走进数据类型及其存储 -> 正文阅读

[C++知识库][C语言数据存储深度解析]-内存数据搞不懂?三千字长文带你走进数据类型及其存储

C语言的基本数据类型

  • 相信大家应该已经很熟悉C语言内置的几个基本数据类型了,这里仅简单罗列:

char------------字符数据类型
short-----------短整型
int---------------整型
long------------长整型
long long-----长整型(plus) (较老的编译器可能没有此类型)
float------------单精度浮点型
double---------双精度浮点型

  • 类型存在的意义:
  • 我们知道不同的数据类型会占用不同的内存空间。在使用时它们时,我们往往是按需使用,以免造成空间的浪费或溢出。
  • 类型还决定着我们看待内存空间的视角
int a=2021;
float A=2021.0f;

这里我们定义了两个变量,整型a和单精度浮点型A,这时存储a和A的两块空间都各自自占据着各自的“立场”,也就是说a开辟的空间中将按照整型的方式存和取,而A则是按照浮点型的方式存和取。

内置类型的基本归类

  • 整型

char / unsigned char(无符号类型) /signed char(有符号类型)
short /unsigned short/signed short
int / unsigned int / signed int
long /unsigned long/signed long
long long同上.

Tips:

  • short [int]是short未省略的写法,long等也一样。
  • 类型前未写(un)signed时,short、long、int等类型直接默认为有符号的对应类型,而char则取决于编译器,大部分编译器都解析其为signed char.

用例深度理解signed和unsigned:

我们知道一个char类型可以存放的是1byte,8bit的大小元素。
这里我们假设此内存中存放二进制数字a1(a2):11111111(补码)
有: unsigned char a1 中无符号位,也就是二进制序列中每一位都是有效位,补码就是其原码、反码,那么a1的值就是255;
亦:signed char a2 中有符号位,首位1代表负数,经过计算,a2的值是-1。

我们更直观的观察一下:

int main()
{
	unsigned char a1 = 255;
	printf("%d\n", a1);
	printf("------\n");
	char a2 = 255;
	printf("%d\n", a2);
	return 0;
}

先找到它们在内存中的数值:(调试起来并在内存窗口中查看)
a1:
在这里插入图片描述
a2:
在这里插入图片描述

可以看到它们的值都是ff(16进制),也就是11111111.
接着看程序运行结果:

故而证明了我们上述理解是正确的,其它类型的数据据此举一反三即可,可以说完全相同。

  • 浮点型

float----4byte
double----8byte(更高精度、更多占用)

  • 构造类型

数组类型
结构体类型-struct
枚举类型-enum
联合类型-union

Tips:

  • 数组的类型:如int arr[10],和之前其它类型一样,我们去掉我们定义的类型名(arr),剩下的就是类型,即此例类型为 int [10]
  • 此段代码可以很直观的展示:
#include<stdio.h>
int main()
{
	int a = 10;
	int arr[10] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(int));
	printf("----------\n");
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(int [10]));
	return 0;
}

其结果为:
在这里插入图片描述

  • 指针类型

int *
char*
float*
···

  • 空类型

void表示空类型(无类型)
常应用于函数返回值类型、函数参数、指针类型等。

整型数据在内存中的存储

  • 计算机中的符号数有三种表示方法,即原码、反码和补码。
    下面我们看一看它们的概念:(点此可直接跳转
    点击下方

正数和无符号数的原码、反码、补码都是相同的。
对于整型来说:数据在内存中均以补码的形式进行存储和计算

为什么呢?
这是因为在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理; 同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

  • 数据存储的又一特点(以整型为例研究)
    我们看这样一段代码
int main()
{
	int a = 10;
	int b = -10;
	return 0;
}

我们再看看其在内存中的存储:
在这里插入图片描述

乍一看,总感觉补码数据存放的顺序有些奇怪,似乎是反了?
我们仔细观察后发现,内存中自上而下,地址不断增加,每个地址指向的空间中的每个字节却是由高到低的顺,我们十进制为10的数字,在16进制存储时似乎本应是00 00 00 0a,但由于这里是在低地址放入了数据的低位,便反向排列,这就是小端存储模式

  • 有小端,就可能有大端[/大笑],我们引入其概念:(源地址
    百度百科
  • 它们存在的意义是什么?
  1. 在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一
    个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为高字节, 0x22为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

你能否写一个程序看看你所使用的编译器是大端存储模式还是小端存储模式?日后我会将程序写出来,你可以和我作一个对比

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

浮点型的数据种类前文我已提到,这里不再过多赘述,先来看一道题目:

int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
} 

先想一想,在脑海中给自己一个答案,然后继续往下看~

这是多年前一家公司的一道笔试题目,第一次做它的时候我也做错了,故而觉得其放在此处很有代表性,它的答案是:
在这里插入图片描述
你做对了吗?为什么结果如此呢?接下来我将解释浮点型数据在内存中的存储方式,若你耐心看完,倘若现在没有头绪的话,到时再回头看此题就会豁然开朗。


我们知道num和*pFloat在内存中表示的是一个数字,但解读的结果为何如此之大?我们需要知道浮点数在计算机内部的表示方法。
根据国际标准IEEE754,任意的一个二进制数字V可以表示成下面的形式:

  • (-1) ^ S* M*2^E
  • 其中(-1)^ S表示符号位,当s=0,V为正数;当S=1,V为负数。
  • M表示有效数字,大于等于1,小于2。
  • 2^ E表示指数位。

这里需要知道十进制的浮点数中小数点之后数字的二进制改写写法:如5.0f,写成二进制是101.0,相当于1.01*2^2。按照上面的写法:我们容易算出S=0,M=1.01,E=2。

IEE754规定:对于32位单精度浮点数,最高位1位是符号位S,接着的8位数是指数E,剩下的23位为有效数字M。
在这里插入图片描述

ps:对于64位,s仍为1bit,E为11bit,M则是52bit。

  • 接下来是有效位E和M的存储方式:

首先是M:

IEEE 754对有效数字M和指数E有一些特别规定。
由于1<=M<=2,即M为1.xxxxxx。在规定中,保存M时,我们总是将第一位舍去(因为它默认是1),只保存 .xxxxxxx,在我们读取的时候再将其加上,这样做多保存一位有效数字。

然后是E:

E是一个无符号数,当E占8bit时,它的取值范围是0~255 ,当其占11bit时,它的取值范围是0~2047。我们h知道,科学计数法中的E可以出现负数,故IEEE 754规定E存入时必须在其真实值上加一个中间数,对于8位的E,加上127,对于11位,则加上1023。
比如2^10的E为10,所以保存为32位的浮点数时,必须保存成10+127=137,也就是10001001.

这里E在内存中取出还可以再分成三种情况:

  • E不全为0或不全为1
    指数E的计算值减去127(1023),得到真实值后再将M加上第一位的i。
  • E全为0
    此时有效数字M不再加1,而是直接还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0很小的数字。
  • E全为1
    此时如果有效数字M全为0,则表示正(负)无穷大,这取决于S是什么。
  • 我们回到这一小节一开始的那个问题:
    我们先写出9的补码:00000000000000000000000000001001
  • 1.以int类型存入,以%d打印,毋庸置疑第一个打印结果是9;
  • 2.n由pFloat维护,pFloat的存在使得它把内存中9的补码认作浮点数序列,
    那么9的补码被理解为:
    0 00000000 00000000000000000001001
    即是:E全0,则E直接为1-127=-126。M也只拿小数点后的数字且不加1,M为0.00000000000000000001001。再根据标准还原出数字为:
    0.00000000000000000001001*2^(-126) 这个数字非常非常小,无限接近于0,又知道%f只能打印6位,那么容易知道结果是0.000000
  • 3 这一次是以浮点数的视角进行存储,那么它在内存中就是:
    1001.0(前面省略),即是(-1)^ 0 * 1.001*2^3
    E就是3然后再加上127,再写成8位二进制序列,S是0,M是1.001000……
    最后的序列就是:
    0 10000010 00100000000000000000000
    这个时候我们又以%d的形式打印,我们就认为内存里是个有符号整数,这个序列自动会被存取为整数序列而不再是浮点数序列,这也是本文得到重点,再次出现。那么它可以直接用计算器得到答案是:1091567616
  • 4 和1是如出一辙,答案自然是9.000000

写在最后

本文可能唯一有理解难度的地方就是浮点数数据相关的重点在于数据在内存中的存和取,内存对于其存的二进制序列如何判断和使用,再根据IEEE754标准进行转变。这也是本文的重点,希望能对你有所帮助。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 11:59:07  更:2021-08-11 11:59:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 18:55:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码