详细讲解C语言14(C语言系列)

发布于:2023-01-20 ⋅ 阅读:(2) ⋅ 点赞:(0) ⋅ 评论:(0)

目录

前言:

数据类型的介绍:

类型的基本归类:

整形家族:

浮点型家族:

构造类型<自定义类型>:

 指针类型:

空类型:

整型在内存中的存储:

原码、反码、补码:

大小端介绍: 

浮点型在内存中的存储: 

常见的浮点数:

浮点数家族:

浮点数的存储规则:

浮点数的取出: 

结束语:


前言:

学习了这么久的C语言,你知道数据在内存中是怎么存储的吗?那么接下来就和我一起来探究一下数据在内存中究竟是怎么存储的。

数据类型的介绍:

之前我们学习了基本的内置类型:char、short、int、long、long long、float、double。

下面我们来具体分类的学习一下。

类型的基本归类:

整形家族:

char int
unsigned char unsigned int
signed char signed int
short  long
unsigned short unsigned long
signed short signed long

浮点型家族:

float

double

构造类型<自定义类型>:

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

 指针类型:

int * pi 整型指针
char * pc 字符指针
float * pf 浮点型指针
void * pv 空指针

空类型:

void表示空指针(无类型)。

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

整型在内存中的存储:

原码、反码、补码:

三种表示方法均有符号位数值位两部分,符号位都是用0表示“正”,用1表示“负”,数值位正数的原、反、补码均相同。

负数原、反、补码的转换规则如下所示:

对于整型来说,数据存放在内存中其实存放的是补码。 

为什么?

在计算机系统中,数值一律用补码来表示和存储。原因在于使用补码,可以将符号位和数值域统一处理。

同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

大小端介绍: 

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

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

例如:

明确了什么是大小端之后,那现在我们来思考一下为什么会有大小端之分呢?

因为如果一个数值超过一个字节了,要存储到内存中,就有顺序的问题。

一般的小型pc机都是小端存储。

那么接下来我们来做几道练习题吧!

题目:设计一个小程序来判断当前机器的字节序。

思想讲解:

我们可以通过1来判断,如果是1就可以判断为小端字节序存储,如果不是1,那么我们就可以判断为大端字节序存储。 

代码展示:

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

代码运行截图:


题目:输入的a、b、c分别为多少?  

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	char a = -1;
	//打印a的分析:
	// 
	//10000000 00000000 00000000 00000001  - 原码
	//11111111 11111111 11111111 11111110  - 反码
	//11111111 11111111 11111111 11111111  - 补码
	//发生截断
	//11111111
	//以%d打印的时候发生整形提升
	//11111111 11111111 11111111 11111111  - 提升后的补码
	//11111111 11111111 11111111 11111110  - 反码
	//10000000 00000000 00000000 00000001  - 原码
	//结果:-1
	signed char b = -1;
	//10000000 00000000 00000000 00000001  - 原码
	//11111111 11111111 11111111 11111110  - 反码
	//11111111 11111111 11111111 11111111  - 补码
	//发生截断
	//11111111
	//以%d打印的时候发生整形提升
	//11111111 11111111 11111111 11111111  - 提升后的补码
	//11111111 11111111 11111111 11111110  - 反码
	//10000000 00000000 00000000 00000001  - 原码
	//结果:-1
	unsigned char c = -1;
	//10000000 00000000 00000000 00000001  - 原码
	//11111111 11111111 11111111 11111110  - 反码
	//11111111 11111111 11111111 11111111  - 补码
	//发生截断
	//11111111
	//以%d打印的时候发生整形提升(由于是unsigned故提升的时候高位补0)
	//00000000 00000000 00000000 11111111  - 原码、反码、补码
	//结果:255
	printf("a = %d, b = %d, c = %d\n", a, b, c);
	return 0;
}

代码运行结果:

注意:

%u:是打印无符号整型,认为内存中存放的补码对应的是一个无符号数。

%d:是打印有符号整型,认为内存中存放的补码对应的是一个有符号数。

 代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	char a = -128;
	//10000000 00000000 00000000 10000000
	//11111111 11111111 11111111 01111111
	//11111111 11111111 11111111 10000000
	//截断
	//10000000
	printf("%u", a);
	//11111111 11111111 11111111 10000000  - a
	return 0;
}

代码运行截图:


浮点型在内存中的存储: 

常见的浮点数:

3.1415

1E10 ---- 1.0 * 10^10

浮点数家族:

float
double
long double

浮点数类型的取值范围限定在:float.h 

整数类型的取值范围限定在:limits.h

浮点数的存储规则:

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

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

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

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

4.2^E表示指数位。 

例如:

IEEE754规定:
 对于32位的浮点数,最高位的1位是符号位S,接着的8位是指数E,剩下的23位位有效位数字M。

float -- 单精度浮点数型

double --- 双精度浮点数型

注意:在M中只存小数点后面的数。 

E为无符号整数,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127,对于11位的E来说,这个中间数为1023.

例如:2^10的E为10,所以在保存成32位浮点数的时候,必须保存成10 + 127 = 137,即10001001。

浮点数的取出: 

指数E从内存中取出分为三种情况

1.E不全为0或不全为1。

指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

2.E全为0。

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

3.E全为1。

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

结束语:

这次小编与大家分享了数据是如何在内存中存储的,希望对大家有所帮助,如果想看其他的知识点还请点击小编主页还有其他的知识专栏哦!想要学习的同学记得关注小编和小编一起学习吧!如果文章中有任何错误也欢迎各位大佬及时为小编指点迷津(在此小编先谢过各位大佬啦!)


网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到