深度剖析数据在内存中的存储

CSDN作者panzii666
喜欢小编写的内容的兄弟们麻烦您们帮忙点点关注,谢谢大家!
看到下面 都是干货,都是小编的一些总结。

前言

`整形和浮点型在内存中的存储形式有着明显不同的区别,为了帮助对这方面还不太了解的小伙伴,我将深度解析这方面的内容。
目录:

  1. 数据类型详细介绍
  2. 整形在内存中的存储:原码、反码、补码
  3. 大小端字节序介绍及判断
  4. 浮点型在内存中的存储解析

标题一:数据类型介绍

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 *
char *
float*
void*

空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。

标题二:整形在内存中的存储:原码、反码、补码

计算机中的整数有三种2进制表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位正数的原、反、补码都相同。
负整数的三种表示方法各不相同。
原码
直接将数值按照正负数的形式翻译成二进制就可以得到原码。
反码
将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码
反码+1就得到补码。
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
例如:

#include<stdio.h>
int main()
{
  int a=20;
  int b=-10;
  //a在内存中的存储以补码形式,又因为上面说过,a正数,正数的原码,反码,补码相同,所以在内存中的二进制是:
  000000000000000000000000000010100``原码/反码/补码`
从左往右数第一个122次方,第二个12的四次方,两个加一块就是20;
b是负数,它的原码,反码,补码各不相同。且听我如何计算:
首先b的原码是:
  10000000000000000000000000001010 原码
  //最右边的第32位代表符号位,正数的符号位是0,负数的符号位是1,所以上边a的第三十二位的数是0;
  b的反码是:
  11111111111111111111111111110101 反码
  b的补码是在反码的基础上加1
  11111111111111111111111111110110 补码
  加1让最左边的1变成2,因为是二进制,逢21,所以变成0,倒数第二位变成1。`
  return 0;
  }
  这里有的注释我就不加//了,以防颜色淡,看不清。
  

标题三:大小端字节序介绍及判断

大小端介绍
什么大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
在这里插入图片描述
教大家如何通过编程判断是大端存储还是小端存储。

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

标题四:浮点型在内存中的存储解析

常见的浮点数:
3.14159
1E10
浮点数家族包括: float、double、long double 类型。
浮点数表示的范围:float.h中定义
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
举例来说:`

#include<stdio.h>
int main()
{
     float a=5.5;
     5.5用二进制表示为 101.1
     相当于(-1^0*1.011*2^2
     
}

在这里插入图片描述
4个字节的数据,符号位占1个bit,指数E占8个bit,有效值M占23个bit.
前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时
候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,
将第一位的1舍去以后,等于可以保存24位有效数字。
前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时
候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,
将第一位的1舍去以后,等于可以保存24位有效数字。

#include<stdio.h>
int main()
{5.532二进制序列为:
    01000000101100000000000000000000
}

为什么5.5的二进制序列是这样的:
我且跟你解释:
在这里插入图片描述
这里还有双精度浮点型数据,和单精度相似,就不多说了。
在这里插入图片描述
最后,也到了文章的结尾,我将跟大家讲解一个例题:

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

在这里插入图片描述
设一个整形变量n=9;同时将n的地址强制类型转化为float型。
1.打印第一个数n,得到9.因为将9赋给整形n,打印也是以%d=整形形式打印,所以是9.
2.打印第二个数
float,因为将9赋给整形n,打印却以%f的形式,由上文我们可知道,整形和浮点型在内存中的存储形式不一样。以整形赋予n,以%f的形式拿出来,得到的值肯定不同,我将带领大家分析一下:在这里插入图片描述
3.打印第三个数num,且听我分析一下:在这里插入图片描述
4.以*float赋值,以**float打印,所以是9.000000。

这就是我的文章,求各位大哥大姐点点关注,谢谢!!!

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值