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语言--数据在内存中的储存(超详细版)

1.数据类型

整形类型:

char :unsigned char, signed char;

short: unsigned short (int),signed short (int);

int:unsigned int,signed int;

long:unsigned long (int),signed long (int)

说明:对于short、int、long类型如果不指出是无符号还是有符号的,编译器默认为有符号的数据。但是对于char类型数据,如果在创建变量时不指出有无符号,那么不同的编译器会有不同的处理方式,比如在vs2019下就默认为有符号的数据。

浮点数类型:

float、double,创建变量时,3.0f表示的是float类型,而3.0表示的是double类型数据。

构造类型:

数组类型、结构体类型、枚举类型、联合类型等。

指针类型:

int* pa、char* pc、float* pf、void* pv。

空类型:

void表示空类型,用于函数返回类型,函数的参数,指针类型等。


2.整型数据的存储方式

变量的创建是需要在内存中开辟空间的,而空间的大小是有不同的类型所决定的。

比如

int a = 20;

int b = -10;

?是如何储存的呢?

2.1原码补码反码

计算机中整数有三种表示方式,原码、反码、补码。三种表示方法均有符号位数值位两部分,符号位0表示正数,1表示负数。而数值位负数的三种表示方式各不相同:

原码:直接把数字按照正负数的形式翻译成二进制序列即可;

反码:原码的符号位不变,数值位取反;

补码:反码+1。

正数的原反补码均相同。?

对于整形来说,数据存放在内存中的都是补码。

2.2大小端存储

int main()
{
	int a = 20;
	int b = -10;
	return 0;
}

写出它们在内存中的储存形式,即补码:

a:00000000 00000000 00000000 00010100

b:10000000 00000000 00000000 000001010 -- 原码

? ?11111111 11111111 11111111 11110101 ----------反码

? ?11111111 11111111 11111111 11110110 -----------补码

?看这样一段代码在内存中是怎样储存的:

?在这里不过只是把补码二进制改成了十六进制的表示方式:

a:00 00 00 14

b:ff ff ff f6

?但是令我们感到诧异的是,在内存中它的存储竟然和它的十六进制序列是相反的。这里就不得不提到大小端存储了。

大端(存储)模式:是指数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中;

小段(存储)模式:是指数据的低位存储在内存的低地址中,而数据的高位保存在内存的高地址中。

特别注意:大小端存储模式是用来安排字节序的,对于char类型数据来讲,不存在大小端存储这一说法。因为char类型只有一个字节。

2.3练习题

写一个程序来判断当前机器的字节序:

int main()
{
	int a = 1;
	char* pa = (char*)&a;
	if (*pa == 0)
    {
        printf("大端存储");
    }
    else
    {
        printf("小端存储");
    }
	return 0;
}
//1的二进制序列为 00000000 00000000 00000000 000000001
//如果是大端存储,在内存中应该为 00 00 00 01
//如果是小端存储,在内存应为 01 00 00 00
//用char*类型的指针存储第一个字节的地址,解引用后访问第一个字节且只能访问第一个字节空间。
//如果是结果是0,大端存储,如果结果是1,小端存储。

3.浮点型数据的存储

常见的浮点数有:3.14、1E10.

3.1一个例子

int main()
{
	int n = 1;
	float* fpa = (float*)&n;
	printf("%d\n", n);
	printf("%f\n", *fpa);

	*fpa = 1.0;
	printf("%d\n", n);
	printf("%f\n", *fpa);
	return 0;
}

?为什么会出现这样的情况,说明浮点数的存储规则是和整形存储规则是不同的。

3.2存储规则

根据国际标准IEEE754任一个二进制浮点数v可以表示为以下形式:

(-1)^S* M * 2^E

? (-1)^S表示的是符号位,s=0则为正数,s=1则为负数;

? M表示有效数字,1<=M<2;

? 2^E表示指数位

?举个例子,10进制中的5.0可以写成二进制中的101.0,也就是1.01x2^2。

?

这时S=0,M=1.01,E=2。当为-5.0时,那么S=1。

IEEE754规定:

对于32位的float的浮点数,最高位的一位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

?对于64位的double的浮点数,最高位的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

IEEE 754 对有效数字 M 和指数 E ,还有一些特别规定。

对于有效数字E:

? 1≤M<2 ,也就是说, M 可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。
IEEE 754 规定,在计算机内部保存 M 时,默认这个数的第一位总是 1 ,因此可以被舍去,只保存后面的 xxxxxx部分。比如保存 1.01 的时候,只保存 01 等到读取的时候,再把第一位的 1 加上去。这样做的目的,是节省1 位有效数字。以 32 位浮点数为例,留给 M 只有 23 位,将第一位的 1 舍去以后,等于可以保存24 位有效数字。

对于指数E:

最重要的一点,指数E在内存中存储时为无符号整形数据(unsigned int),这就说明着,如果E为8位,他的取值范围为0~255,如果E为11位,他的取值范围为0~2047。但是科学计数法中,指数可以是负号。所以在IEEE754中规定,存入内存E时的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如2^20的E是10,所以保存成32位浮点数时,必须保存成20+127=147,即1001 0011。

将E从内存中拿出来又可以分为这几种情况:

E不为全0,全1:

这时浮点数就采用规则表示,即指数E减去127(或1023)得到真实值,再将有效数字M前加上第一位的1。例如:0.5的二进制表示就是0.1,由于规定M必须大于一,小数点右移一位,得到1.0*2^(-1),所以指数就应该是-1+127=126.表示为01111110,而1.0去掉位数就是0,补齐就全是0.

0 01111110 00000000000000000000000

E为全0:

这时M全为0,浮点数的指数真实值应该是一个很小的数,因为真实值加127才等于0,说明真实值应该是-127,而2^(-127)是一个很小的数。接近+-0。具体看符号位

E为全1:

这时,M全为0,说明真实值加127等于255,真实值应该是128,而2^128是一个很大的值,接近于+-无穷大。具体看符号位。


这时解释前面代码打印的数据就很好解释了:

n为整形数据1,是这么储存在内存中的:

00000000 00000000 00000000 00000001

当以%d打印它时,就是以整形形式打印它,所以是1。当以%f打印它时是以浮点型打印的,所以应该分析它的储存形式:

0 00000000 00000000000000000000001

S为0,E为全0,M为000…1。所以应该是无穷小的一个数,所以打印0.000000。浮点数不管是float还是double,打印时默认小数点后面都是六位数,没有数的补0。

?当解引用了以后,*fpa中存储的就是浮点型数据1.0了:

0 01111111 00000000000000000000000

S为0,E为0+127,M为全0。

在这时以%f打印就是打印1.0,以%d打印是以整形形式输出所以是一个比较大的数,通过计算器计算确实是打印出来的数据。?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 09:43:57  更:2021-11-27 09:45:40 
 
开发: 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年11日历 -2024/11/28 3:55:27-

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