C语言进阶——数据在内存中的存储

所属专栏:C语言——梦想系列_Yohifo的博客-CSDN博客

目录

前言

正文

数据分类

️整型家族

️浮点型家族

️构造家族

️指针家族

️空类型家族

整型数据在内存中的存储 

️原码、反码、补码 

️大小端字节序

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

️存入

️取出 

️例题

总结


前言

  经过前面博客的介绍,我们的C语言初阶已经学完了。现在我们可以进入更深层次的C语言世界了,而本文是我们进阶的首篇文章,主要是介绍各种数据在内存中的存储情况,比如有符号char的最大值是多少、整型数据与浮点型数据在内存的存储方式有何不同等,学会这些知识能增加我们的内功,真正做到了然于心。

C语言进阶——数据在内存中的存储_第1张图片


正文

我们C语言中的有七种基本数据类型,可以分为三种:整型、实型、字符型。

C语言中的基本数据类型

short                       短整型                     %hd               2字节
int                            整型                        %d                  4字节

long                      长整型                    %ld             4~8字节

long long                 更长整型                 %lld               8字节
float                         单精度浮点型          %f                  4字节
double                     双精度浮点型          %lf                 8字节
char                         字符型                     %c                 1字节

数据分类

根据各数据的特点,可将数据分为以下几类:

️整型家族

char

当我们选择char时,是否带有符号是由编译器决定的,有符号和无符号 char 的取值范围不同

char 大小为1字节=8比特,因此在 char 中至多有八个可用位。

C语言进阶——数据在内存中的存储_第2张图片

signed char 有符号 char

C语言进阶——数据在内存中的存储_第3张图片

unsigned char 无符号 char

C语言进阶——数据在内存中的存储_第4张图片

short

short比 char 大1字节,因此所表示范围值会比 char 大很多,最大值同样是无符号表示

C语言进阶——数据在内存中的存储_第5张图片

signed short

C语言进阶——数据在内存中的存储_第6张图片

unsigned short

C语言进阶——数据在内存中的存储_第7张图片

int

int为标准的4字节,32比特位,有无符号的 int 最大值差别依旧很大

C语言进阶——数据在内存中的存储_第8张图片

signed int

C语言进阶——数据在内存中的存储_第9张图片

unsigned int

C语言进阶——数据在内存中的存储_第10张图片

long

long的大小是4~8字节,这里我们取8字节,相当于long long,作为最大的数据类型,long在使用时几乎很难造成溢出,因为比较无符号long最大值就为922京(9*10^18)

C语言进阶——数据在内存中的存储_第11张图片

signed long

C语言进阶——数据在内存中的存储_第12张图片

unsigned long 

C语言进阶——数据在内存中的存储_第13张图片

️浮点型家族

浮点型家族就两个:float与double,float是4字节,double则是8字节,可表示的范围也是非常大,由于浮点型在内存中存储时比较复杂,不再依靠原反补这套系统,而是拥有属于自己的存储方式。有关浮点型数据在内存中的存储情况,将会专门在后面解释。

️构造家族

构造家族外部依赖性强,有以下四种:

数组类型            arr[ ]
结构体类型        struct
枚举类型            enum
联合类型            union

构造家族成员都需要依靠外部定义的数据,比如数组,需要定义大小;结构体,需要声明内部的变量成员;枚举类型则需要根据变量数来确定枚举值等

️指针家族

指针家族中包括了各种类型的指针变量,比如常用的有:

int*      pi             整型指针,指向整型数据
float*   pf            浮点型指针,指向浮点型数据
char*   pc           字符型指针,指向字符型数据
void*   pv            空指针,能指向所有的数据,但无法进行操作,作临时指针

️空类型家族

空类型(void)指没有具体的数据类型,通常用于函数返回值、函数参数、临时指针中。

C语言进阶——数据在内存中的存储_第14张图片

整型数据在内存中的存储 

整型数据有三种状态:原码、反码、补码,原码就是将原数据转换为二进制后的序列,序列中的最高位为符号位(0为正数,1为负数),反码则是将原码除符号位外全部取反(0变为1,1变为0),补码则是在反码的基础上+1,整型数据在内存中都是以补码的形式存储的,因为正数原码、反码、补码均相同,因此我们只有遇到负数时才刻意去求补码。

️原码、反码、补码 

原码:将数值向二进制进行转换,要注意符号位,0为正数,1为负数
反码:将原码除符号位外全部取反,比如10000001,取反为11111110
补码:再反码的基础上进行+1,比如11111110,+1后变成11111111

至于为什么需要补码这个概念?

因为CPU中只有加法器,在执行减法操作时会将被减数转换为一个负数,然后再进行相加

C语言进阶——数据在内存中的存储_第15张图片

 补码的产生使得加法转换为减法后的计算结果依旧正确,而且因为转码的运算过程是相同的,不需要借助额外的硬件电路,因此计算速度上几乎无差异。

️大小端字节序

在我们的内存中存在两种不同的存放标准,一种是大端存储,另一种则是小端存储,不同编译器所支持的存储顺序有所不同,比如我们的VS2019,使用的就是小端字节序存储数据。

大端存储:指将数据高位次存放在内存的低地址中,而低位次则是存放在内存的高地址中  
当为大端存储时,十六进制会正着显示
小端存储:指将数据高位次存放在内存的高地址中,而低位次则是存放在内存的低地址中
当为小端存储时,十六进制会倒着显示

C语言进阶——数据在内存中的存储_第16张图片

C语言进阶——数据在内存中的存储_第17张图片

大小端相关笔试题(百度 2015 笔试题)

概念不必阐述,让我们直接开始设计程序进行判断

C语言进阶——数据在内存中的存储_第18张图片

//判断大小端
int main()
{
	int a = 1;//十六进制表示为 00 00 00 01
	char* pa = (char*)&a;//利用字符型指针访问一字节
	if (*pa == 1)
		printf("小端存储\n");
	else
		printf("大端存储\n");
}

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

️存入

浮点数在内存中表示时比较复杂,于是电气和电子工程协会(IEEE)754标准便这样规定了浮点数在内存中存储规则:任何一个浮点数V都可以写成  V=(-1)^S*M*2^E ,其中S控制符号位,为1时V为负数,为0时V为正数;M为有效数字,在1~2这个区间内;2^E则表示指数位。

C语言进阶——数据在内存中的存储_第19张图片C语言进阶——数据在内存中的存储_第20张图片

 由此可见浮点数在内存中的储存与整型完全不一样,也就是说如果在输入(输出)时格式匹配错误,那么数据肯定就是有问题的!!!

单精度浮点型(float)有32比特位,规则在上面,而双精度浮点型(double)有64位,规则跟32位几乎一致,不过在空间分配和指数E的中间值上略有差异

C语言进阶——数据在内存中的存储_第21张图片

️取出 

存入很复杂,取出也很复杂,光是取出的情况就有三种:

  • 1.指数E非全0或非全1时,常规取出,如果存的时候加了中间值127(或1023)取的时候就要减去中间值127(或1023),这是比较常见的取出形式。
  • 2.指数E为全0时,若指数E为全0,说明初始E为-127,可以看出原浮点数是一个非常小的数,无限接近于0,因此这个数字取出来将会是一个很小很小的数。
  • 3.指数E为全1时,若有效数字M全为0,表示正负无穷大。

️例题

 模拟将整型存入浮点型,将浮点型存入整型的场景

C语言进阶——数据在内存中的存储_第22张图片

//模拟
int main()
{
	int a = 9;
	float* pa = &a;
	printf("%d\n", a);
	printf("%f\n", *pa);
	*pa = 9.0;
	printf("%d\n", a);
	printf("%f\n", *pa);
	return 0;
}

总结 

  数据类型算是C语言中的底层部分了,不同数据类型的数值轮回也是合情合理,在做题时注意看是否有符号,这样在进行计算时就可以判断出是否接近边界;不同类型的数据都有其应用场景,只有做到场景匹配了,程序效率才会最大化。总的来说,无论是反码相加还是浮点数的存储,都是非常巧妙的设计,是无数前辈绞尽脑汁的最优解,正是因为有了这些规则,今天我们才能看到如此完善的C语言体系。今天,我们站在巨人的肩膀上,明天,我们也许就能实现巨人们远大的理想!

  如果你觉得本文写的还不错的话,期待留下一个小小的赞,你的支持是我分享的最大动力!

  如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正

C语言进阶——数据在内存中的存储_第23张图片

你可能感兴趣的:(C语言——梦想系列,c语言,学习)