0
点赞
收藏
分享

微信扫一扫

知识巩固之Java序列化

目录

数据类型详细介绍

在C语言的初期学习中,我们已经学习过基本的内置数据类型:

char        //字符数据类型
short       //短整型
int         //整形
long        //长整型
long long   //更长的整形
float       //单精度浮点数
double      //双精度浮点数

以及他们所占存储空间的大小。

数据类型的意义:

类型的基本归类:

整形家族:(一般把char类型也归类于整型中,因为内存中char类型存储的是字符的ASCII码值

int 
	 unsigned int
	 signed int
short
	 unsigned short [int]
	 signed short [int]
long
	 unsigned long [int]
	 signed long [int]
char
	 unsigned char
	 signed char

在这里插入图片描述

int类型分为unsigned intsigned int无符号整型和有符号整型
这里的有无符号指的是正负号,也就是说signed int既可以表示正数也可以表示负数,而unsigned int只能表示正数。
当我们只写int时,编译器默认int为signed int。也就是说int 和 signed int互相等价
适用范围:

假如我们不小心给unsigned int类型的数据赋值了负数,思考一下结果会怎么样?
注:

#include <stdio.h>
int main()
{
	unsigned int b = -10;
	printf("%u\n", b);
	return 0}

在这里插入图片描述
在这里插入图片描述

屏幕上输出了一个很大的数字,内存中b中存储的也是这个数字,为什么呢?

在这里插入图片描述
我们存入-10的补码,但unsigned int b会认为这个二进制数字是一个数字的原码并进行存储。


在这里插入图片描述

short类型是短整型,分为 unsigned short [int] 和 signed short [int],平时使用时可省略最后的int。
后面几个数据类型和int类型功能几乎一样,这里不过多赘述。


浮点数家族:

float//单精度浮点数
double//双精度浮点数

浮点数类型也可以分为有符号浮点数和无符号浮点数
浮点数用来定义一些实型数据(小数)。
示例:

#include <stdio.h>
int main()
{
	float a = 1.1f;
	double b = 3.14;
	printf("%f\n", a);
	printf("%lf\n", b);
	return 0;
}

在这里插入图片描述
注:

在这里插入图片描述

浮点数的内存存储在后文中也会讲到。


构造类型:

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

数组类型
示例:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7 };
	char arr2[] = "abcdef";
	return 0;
}

当我们定义好一个数组后,去掉它的数组名,剩下的就是这个变量的数据类型:

int [10]
char []

结构体在前面的文章中讲过,有需要的可以去阅读一下:

枚举和联合会在后续的自定义类型详解文章中详细介绍,这里先认识一下,后期详细讲解。


指针类型:

int *pi;
char *pc;
float* pf;
void* pv;

有关指针的知识在前面的文章中也讲过,有需要的可以去阅读一下:

空类型:


整形在内存中的存储

我们之前讲过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。
那接下来我们谈谈数据在所开辟内存中到底是如何存储的?
比如:

int a = 10;

我们知道为 a 分配四个字节的空间。
那如何存储?

原码、反码、补码

下来需要先了解下面的概念:

对于整形来说:数据存放内存中其实存放的是补码。

为什么呢?

在这里插入图片描述

示例:

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

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

我们可以看到对于a和b分别存储的是补码。但是我们发现顺序有点不对劲。
这是又为什么?
这里就涉及到数据存储到内存时,大小端的知识。

大小端字节序介绍及判断

什么大端小端

在这里插入图片描述

为什么有大端和小端

练习:

思路:
判断机器采用哪种字节序,就需要使用一个数据来进行验证,假如我们定义了一个整型数值a ,当我们打印它的第一位字节时,不同的值就可以代表机器的字节序了。

实现代码:

#include <stdio.h>
int main()
{
	int a = 0x1;
	char* p = (char*)&a;
	if (*p)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

或者

#include <stdio.h>
int check_sys()
{
	int i = 1;
	return (*(char*)&i);
}
int main()
{
	int ret = check_sys();
	if (ret)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

在这里插入图片描述
当前编译器VS2019采用的是小端字节序存储。


浮点型在内存中的存储解析

常见的浮点数:

浮点数存储的例子:

#include <stdio.h>
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 在内存中明明是同一个数,为什么浮点数和整数的解读结果会差别这么大?
这里需要先讲讲浮点数存储规则

浮点数存储规则

举例来说:

IEEE 754规定:

在这里插入图片描述

在这里插入图片描述

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

0 01111110 00000000000000000000000

E全为0

E全为1

关于浮点数的表示规则,就说到这里。

解释前面的题目:
在这里插入图片描述

下面,让我们回到一开始的问题:为什么 0x00000009 还原成浮点数,就成了 0.000000 ?
首先,将 0x00000009 拆分,得到第一位符号位s=0,后面8位的指数 E=00000000 ,最后23位的有效数字M=000 0000 0000 0000 0000 1001。

9 -> 0000 0000 0000 0000 0000 0000 0000 1001

由于指数E全为0,所以符合上一节的第二种情况。因此,浮点数V就写成:

V=(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146)

显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000。


在这里插入图片描述

再看例题的第二部分。
请问浮点数9.0,如何用二进制表示?还原成十进制又是多少?
首先,浮点数9.0等于二进制的1001.0,即1.001×2^3。

9.0 -> 1001.0 ->(-1)^01.0012^3 -> s=0, M=1.001,E=3+127=130

那么,第一位的符号位s=0,有效数字M等于001后面再加20个0,凑满23位,指数E等于3+127=130,即10000010。
所以,写成二进制形式,应该是s+E+M,即

0 10000010 001 0000 0000 0000 0000 0000

这个32位的二进制数,还原成十进制,正是 1091567616 。


本篇关于数据在内存中的存储的讲解就到此结束了,感兴趣的的小伙伴点点赞,点点关注,谢谢大家的阅读哦!!!
下一篇将会进入C语言指针进阶的学习,会对指针的各种使用进行详细介绍,点点关注,后期不错过哦。😘
你们的鼓励就是我的动力,欢迎下次继续阅读!!!😘😘😘

举报

相关推荐

0 条评论