深入了解C语言中数据的存储

C语言是贴着计算机运行的一种语言
相对于其他语言我们更需要了解C语言中不同的数据都是怎么存储的。

深度剖析的话 可将其分为四个方向
1. 数据类型介绍
2. 整形在内存中的存储:原码、反码、补码
3. 大小端字节序介绍及判断
4. 浮点型在内存中的存储解析

我们从第一个开始来逐个进行解读

1. 数据类型介绍

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

对数据类型的进行一个基本归类 我们可以将其分为以下五组
整形家族:
浮点数家族:
构造类型:
指针类型
空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。

2. 整形在内存中的存储

我们知道变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。
我们要知道这些空间计算即是如何开辟的?计算机又是如何将数据存储起来的?
我么先来了解这几个概念
计算机中的有符号数有三种表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位
三种表示方法各不相同。
原码
直接将二进制按照正负数的形式翻译成二进制就可以。
反码
将原码的符号位不变,其他位依次按位取反就可以得到了。
补码 反码加1就能得到原码的补码
正数的原、反、补码都相同。

对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理; 同 时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需 要额外的硬件电路。

3.大小端介绍

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

一道判断大小端的题目

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

这道判断大小端的题目巧妙地运用了C语言的隐式类型转换是字节的截断和提升 从计算即大小端存储差异入手 从而巧妙地进行解答

4.浮点型在内存中的存储

我们曾经学习过的浮点数包括: float、double、long double 类型。
但是浮点数与整形在计算机中的存储却大不相同
我们来看一段代码

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

运行结果如图
在这里插入图片描述
解读:
根据国际标准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.01×2^2 。 那么,按照上面V的格式,可以得出s=0, M=1.01,E=2。 十进制的-5.0,写成二进制是-101.0 ,相当于-1.01×2^2 。那么,s=1,M=1.01,E=2。

因此对于计算机来说也得按照这种方法进行存储
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

特别规定.
1≤M<2
M可以写成 1.xxxxxx 的形 式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。
指数E
首先,E为一个无符号整数 所以IEEE 754规定,存入内存时E的真 实值必须再加上一个中间数,对于8位的E,这个中间数是127

我们经过简单了解现在再对上面的题进行一个合理的解释
对于前两个printf 首先
int n=9;
然后我们将n的地址取出来存入了一个指针变量中
我们知道 地址在内存中一般是占四个字节的 int的变量在内存中也是占四个字节进行存储的
注意
float*是一个浮点型的指针
int位整型变量
我们将整形取地址然后强转成一个float的地址进行存储 显然当我们进行读取时候 会出现错误
n=9的二进制 00000000 00000000 00000000 00001001
当转成float时 因为 float数据分三部分进行存储
对于 00000000 00000000 00000000 00001001 将该数据看作浮点数的话 是一个很小的数据 (-1)^0 * 10 ^0 *1.0000000…… 此处省略
因此打印出来的结果就是一个0.000000 (float数据打印时小数点后跟默认六位)

然后对后面两个printf进行分析
我们在打印前首先对pfloat的值进行了一个改变 --9.0
因此 n的地址的值就发生了改变 同样的
pfloat的值也发生了改变
*pfloat打印出来的值是9.000000 很容易理解
n的值打印出来是一个奇怪的数字
9 的二进制表示 00000000 00000000 00000000 00001001
按照上述规则
9.0内存中存储 0 10000010 001 0000 00000000 00000000
我们将其转化为十进制发现正好是
1091567616

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值