C语言详细分析不同类型数据在内存中的存储

目录
  • 数据类型的介绍
  • 类型的基本归类
  • 整形在内存中的存储
  • 大小端介绍
  • 一道笔试题
  • 浮点数在内存中的存储
  • 浮点数存储规则
  • 剖析题目

数据类型的介绍

在我们之前的学习当中我们已经介绍了基本的内置类型

char 字符数据类型

short 短整型

int 整形

long 长整型

long long 更长的整形

float 单精度浮点数

double 双精度浮点数

这些类型的意义是:

1.使用这个类型开辟内存空间的大小,大小决定了使用范围

2.如何看待内存空间的视角。

类型的基本归类

整形

整形中分为有符号整形和无符号整形,因为我们生后中有些数值需要有正数和负数之分,例如温度我们就可以使用有符号整形,但是有些不需要负数的数值例如身高,我们就可以使用无符号整形。

char

unsigned char

signed char

short

unsigned short [int]

signed short [int]

int

unsigned int

signed int

long

unsigned long [int]

signed long [int]

浮点型

float

double

构造类型

数组类型

结构体类型 struct

枚举类型 enum

联合类型 union

指针类型

int pi;

char pc;

float pf;

void pv;

空类型

void表示空类型(无类型)

通常应用于函数的返回类型,函数的参数、指针类型

整形在内存中的存储

我们都知道,创建一个变量需要在内存中开辟空间,那变量究竟是怎么在内存当中存储的呢。我们又要提到原码、反码、补码的概念了。

在计算机中整数有三种表示方式即原码、反码、补码,他们都有符号位和数值位,符号位用0表示正数,用1表示负数。

正整数的原码、反码、补码相同,都是直接将属猪按照正负数的形式翻译成二进制形式就可以得到原码。

负整数的原码、反码、补码

原码

直接将数值按照正负数的形式翻译成二进制形式就可以得到原码

反码

将原码的符号位不变,其他位一次按位取反就可以得到反码

补码

反码+1就是补码

对于一个整形,数据在内存当中存放的其实是他的补码。那么为什么是补码而是不是原码呢,原因是使用补码,可以将符号位和数值域统一处理,同时加法和减法也可以统一处理,我们的cpu只有加法器,此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

例如:

1 - 1
因为cpu中只有加法器,所以我们需要将减法转化为加法,1+ (-1)如果内存中存储的是原码,那么他们相加的结果为
00000000 00000000 00000000 00000001 1的原码
10000000 00000000 00000000 00000001 -1的原码
10000000 00000000 00000000 00000010 相加为-2
我们运算的答案是错误的,但是当我们存储的是补码时:
00000000 00000000 00000000 00000001 1的补码
11111111 11111111 11111111 11111111 -1的补码
00000000 00000000 00000000 00000000 相加0
使用补码运算时,得到正确的答案

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

如上图编译器为了方便显示的是16进制数,其实对于一个整形,数据在内存当中存放的还是他的补码,我们可以是尝试还原一下。

例如**-10**
原码:10000000 00000000 00000000 00001010
反码:11111111 11111111 11111111 11110101
补码:11111111 11111111 11111111 11110110
将他的补码转换成16进制就变成了ff ff ff f6,跟我们通过调试看到的内容一样

但是我们通过对比发现虽然存储的是补码,但是存储的顺序好像不一样,这是怎么回事呢?

大小端介绍

当我们的数据大于一个字节时,数据的存储就有了顺序问题。例如:一个十六进制数0x11223344,我们说11为数据的高位,44为数据的低位。

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

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

int main()
{
	int a = 0x11223344;
	return 0;
}

我们通过调试得出,在vs2019中为小端存储模式,因为数据的低位44存储在地址处,高位11存储在高地址处。

一道笔试题

我们通过一道笔试题来巩固一下我们刚才所总结的知识。题目:请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。

小端字节序存储

把数据的低位存储在内存的低地址处,高位字节的内容,存储在内存的高地址处 大端字节序存储 把数据的低字节的内容,存放到内存的高地址处,高字节内容,存放在低地址处

int check_sys()
{
	int a = 1;
	return *(char*)&a;
}
int main()
{
	if (check_sys() == 1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}

浮点数在内存中的存储

首先我们通过一段代码来观察浮点数在内存中的存储

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;
}

以我们的认识,使用%d打印应该打印9使用%f打印应该打印9.0,但事实是这样的嘛

我们将代码跑起来发现,并非我们所认识的,那这说明了什么,说明了浮点型与整形在内存当中的存储规则是不一样的,那我们先了解一下浮点数究竟怎么储存的。

浮点数存储规则

根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数v可以表示成下面的形式:

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

(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。

M表示有效数字,大于等于1,小于2。

2^E表示指数位。

例如:十进制5.0,写成二进制是101.0,相当于1.0122

所以s = 0,m = 1.01, e = 2。

IEEE 754规定:

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

IEEE 754对有效数字M和指数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。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

既然我们可以将浮点数存储,我们就可以将他们取出来,但是指数E从内存中取出分为三种情况:

E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将 有效数字M前加上第一位的1。

E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

E全为1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)

剖析题目

这些就是浮点数在内存当中的存储规则,了解了这些后让我们回到最开始的那道题,我们进行分析。

首先我们创建了一个整形变量,那么他在内存中存储的是什么呢?是他的补码00000000000000000000000000001001,当我们将他看作一个浮点数打印时,我们可以得到S = 0,M = 000 0000 0000 0000 0000 1001,E = 00000000。所以经过计算(-1)^ 0 × 0.00000000000000000001001×2 ^ (-126) = 1.001×2 ^ (-146), 所以根据规则他是一个非常接近0的数,使用浮点数打印就是0.000000

笔试题的第二部分,我们将一个浮点型使用整形打印,同样的道理,我们先将9.0用浮点数的方式存进内存当中,9.0写成二进制为1001.0,可以写成(-1)^0 * 1.001*2^3,我们可以推出二进制形式:0 10000010 001 0000 0000 0000 0000 0000,所以将他作为一个整形打印时就会是一个非常大的数为1091567616

到此这篇关于C语言详细分析不同类型数据在内存中的存储的文章就介绍到这了,更多相关C语言数据存储内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中数据是如何存储在内存中的

    目录 前言 ‍数据类型介绍 ‍整形数据在内存中存储 ‍浮点型数据在内存存储 前言 在计算机内存中,数据的存储方式都是以0和1的形式存储,也就是二进制的形式,数据是如何向内存写入的呢?整形数据以补码的形式存储,浮点型的存储规则较多,类似于科学计数法. ‍数据类型介绍 为什么需要有这些数据类型? 数据类型解决了数据存储的问题. ‍整形数据在内存中存储 整数中有三种二进制表示形式,分别是原码.反码.补码,正整数的原码 = 反码 = 补码,通常取最高位作为符号位. 原码:直接将正负整数按照二进制形式转换

  • C语言中数据在内存如何存储

    目录 数据类型 类型的基本归类 整形 浮点型 构造类型(自定义类型) 指针类型 空类型 整形在内存中的存储 大小端字节序 储存时数据发生截断以及整型提升 浮点型在内存中的存储 浮点型和整形在内存中的储存方式不同 拿出这些储存的数据(三种情乱) 情况一:E不全为0或不为全1 情况二:E全为0 情况三:E为全1 数据类型 常见的数据类型 常见的数据类型 字节 char 字符数据类型 1 short 短整型 2 int 整形 4 long 长整型 4 long long 更长的整形 8 float 浮

  • C语言编程数据在内存中的存储详解

    目录 变量在计算机中有三种表示方式,原码反码,补码 原码 反码 补码 总结一下 浮点数在内存的储存 C语言中,有几种基本内置类型. int unsigned int signed int char unsigned char signed char long unsigned long signed long float double 在内存中创建变量,会在内存中开辟空间,并为其赋值. int a=10; 在计算机中,所有数据都是以二进制的形式存储在内存中. 变量在计算机中有三种表示方式,原码反

  • C语言中数据如何存储进内存揭秘

    目录 内存简单介绍 整数与字符在内存中的存储 浮点数在内存中的存储 大小端存储模式及简介 总结 内存简单介绍 大家肯定经常听说内存这个词,内存到底是什么呢? 在计算机中,进程都要加载进内存中,也是我们各种数据的流通途径,C语言中,大家肯定都知道指针变量,指针变量中保存的就是内存的地址,那么,什么是内存的地址呢? 内存的单位是字节 对于32位的机器,有32根地址线,每根地址线在寻址时,产生的高低电压分别为0/1,那么32根地址线产生的地址就会是 00000000000000000000000000

  • 关于C语言中数据在内存中的存储详解

    前言 1. 数据类型详细介绍 2. 整形在内存中的存储:原码.反码.补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析 一.数据类型介绍 1.类型的基本归类 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] 2.浮点型家族

  • C语言数据的存储超详细讲解下篇浮点型在内存中的存取

    目录 前言 浮点型在内存中的存储 浮点数存储的例子 浮点数存储规则 IEEE 754规定 IEEE 754对有效数字M的特别规定 IEEE 754对指数E的特别规定 存入内存是E的规定 从内存取出时E的规定 举例 1 举例 2 举例 3 判断两个浮点数是否相等? 总结 前言 本文接着学习数据的存储相关的内容,主要学习浮点型数在内存中的存储与取出. 浮点型在内存中的存储 常见的浮点数:3.14159.1E10 浮点数家族包括: float.double.long double 类型 浮点数表示的范

  • C语言数据(整数、浮点数)在内存中的存储

    本篇主要讨论:整数.浮点数在内存中是怎么保存的! 数据类型详细介绍 在前面C语言基础概览中,已经提到过了基本的C语言内置类型,但C语言的数据类型有无数种~ 但是可以把这些类型分为几个大类: 类型的归类: 存整数的 char,short,int,long,long long及所配套的unsigned,int*,int[]- 2.存浮点数的 float,double,float[]- 结构体(结构体在内存中的存储后面在进行讨论~) 整数在内存种的存储: 1.字节序 2.补码 内存窗口 调试模式下的内

  • C语言数据在内存中的存储详解

    目录 文章摘要 一.C语言的数据类型 数据类型基本分为: 二.隐式类型转换 1.什么是隐式类型转换 2.整型提升 3.类型转换 三.机器大小端 1.什么是大小端 2.大小端在截断的应用 3.判断当前机器的字节序是大端还是小端 四.整型在内存中的存储 1.原码.反码.补码 2.举例实践整型数据在内存的存储 总结 文章摘要 本文通过内存底层原理,帮你透彻了解数据存储进内存与从内存中读取的区别以及不同数据类型下数据计算.赋值的变化情况 要透彻理解这些,必须知道隐式类型转换以及机器大小端的概念,本文会对

  • C语言详细分析不同类型数据在内存中的存储

    目录 数据类型的介绍 类型的基本归类 整形在内存中的存储 大小端介绍 一道笔试题 浮点数在内存中的存储 浮点数存储规则 剖析题目 数据类型的介绍 在我们之前的学习当中我们已经介绍了基本的内置类型 char 字符数据类型 short 短整型 int 整形 long 长整型 long long 更长的整形 float 单精度浮点数 double 双精度浮点数 这些类型的意义是: 1.使用这个类型开辟内存空间的大小,大小决定了使用范围 2.如何看待内存空间的视角. 类型的基本归类 整形 整形中分为有符

  • C语言数据在内存中的存储流程深入分析

    目录 前言 类型的基本分类 整型 浮点数 自定义类型 整型在内存中的存储 原码.反码.补码 大端和小端 如何判断编译器是大端还是小端 浮点数在内存中的存储 总结 前言 C语言中有char.short.int.long.long long.float和doubole这些数据类型.这些数据类型也叫内置类型. 所占存储空间的大小: 数据类型 所占存储空间的大小 char 1个字节 int 4个字节 short 4个字节 long 4个字节 long long 32位平台下占4个字节 ,64位平台下占8

  • C++浅析数据在内存中如何存储

    目录 一.数据类型 二.原码反码补码 三.大小端 整型提升 一.数据类型 数据类型有7种: char            字符型     short          短整型    int               整型   long            长整型   long long    更长整型   float            单精度浮点数    double        双精度浮点数 二.原码反码补码 计算机中的整数有三种2进制表示方法,即原码.反码和补码. 三种表示方法均

  • C语言 详细分析结构体的内存对齐

    目录 一.结构体 二.结构体内存对齐 1.非嵌套结构体的大小 2.含嵌套结构体的大小 三.为什么要内存对齐 1.平台原因(移植原因) 2.性能原因 一.结构体 结构体 (struct)是一种数据结构,可以包含很多数据类型,可以实现比较复杂的数据结构. 常见的int,char类型变量,我们可以一眼看出占多少字节,但对于结构体,可就有点难度了. 让我们来猜猜以下程序的输出 struct S1 { char c1; int i; char c2; }; struct S2 { char c1; cha

  • C语言详细分析讲解多文件的程序设计

    目录 一.多文件与编译器链接 二.多文件之间的相互访问 三.关于#include 四.头文件使用的一些原则 五.再论全局变量 六.注意事项 七.实验程序 八.小结 一.多文件与编译器链接 如下图所示,.o 为目标文件,链接器将不同的目标文件装配组合在一起形成一个可执行文件. 二.多文件之间的相互访问 每个文件可以定义功能接口(可被其它文件访问的函数或数据) 源文件:代码实现文件,后缀为.c 头文件:源文件的接口定义文件,后缀为.h 当需要使用其它文件提供的功能时,包含对应的头文件 语法: #in

  • C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

    目录 C语言内存管理 一.动态空间申请 二.动态空间的扩容 三.释放内存 C语言内存管理 malloc && realloc && free && calloc c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理. 我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组 int nums[

随机推荐