深度理解数据在内存中的存储

简介: 深度理解数据在内存中的存储

       今天我主要给大家带来的是整形数据在内存中的存储和浮点数据在内存中的存储。在我们常用的数据类型包括int型,char型,double型,short型,float型。在这些数据类型中我们可以分为整形家族浮点家族

1.整形家族

整形家族主要包括

2.大小端

大端存储是指数据的低位放在高地址存储,数据的高位放在低地址存储。

小端存储是指数据的低位放在低地址存储,数据的高位放在高地址存储。

       例如在我的电脑中打开vs,写一个变量a=0x11223344,在这里低位是44,高位是11,我们进入调试

它在内存中为44 33 22 11,故我们可以画图为

        因此我们可以看到我的电脑为小端存储。对于如何判断电脑的存储方式我们可以写一个判断的小程序,代码如下:

#include <stdio.h>
int main()
{
  int a = 1;
  char* p = (char*)&a;
  if (*p == 1)
    printf("小端存储");
  else
    printf("大端存储");
  return 0;
}
       在电脑中,数据是以 二进制的方式进行存储, int类型占4个字节在64位机器中占32个bite位它的二进制位00000000000000000000000000000001。 char类型占1个字节,8个bite位。我们利用指针再将其 强制转化为char*类型,由于我们指向离低地址近的位置,如果是大端存储则为00000000,小端存储则指向00000001.故我们运行程序可以得到是哪一种存储方式。

3.%d和%u

%d打印的是10进制,有符号的类型;

%u打印的是10进制,无符号的类型;

4.练习

4.1练习一

代码如下

#include <stdio.h>
int main()
{
  char a = -1;
  signed char b = -1;
  unsigned char c = -1;
  printf("a = %d b = %d c = %d", a, b, c);
  return 0;
}

       我们知道整形的数据在内存中以二进制的形式存在,也就是数据的补码,要想知道数据补码,需要得到它的源码和反码。对于-1,它的原码是10000000000000000000000000000001,反码为11111111111111111111111111111110,

补码为11111111111111111111111111111111。由于char占1个字节也就是8个bite位故a,b,c在内存中都是11111111的形式存储。由于需要以%d的形式输出所以需要进行整型提升a的类型为char,符号位为1所以补1,补码为11111111111111111111111111111111,反码为10000000000000000000000000000000;原码为10000000000000000000000000000001故为-1。b的类型为signed char属于有符号的char需要以%d的形式输出所以需要进行整型提升符号位为1所以补1,补码为11111111111111111111111111111111,反码为10000000000000000000000000000000;原码为10000000000000000000000000000001故为-1。c的类型为unsigned char 类型属于无符号类型补码原码反码相同在进行整型提升时补0,补码原码反码为00000000000000000000000011111111.输出255.

4.2 练习二

代码如下

#include <stdio.h>
int main()
{
  char a = -128;
  printf("%u", a);
  return 0;
}

        -128的补码为11111111111111111111111110000000由于时char类型所以10000000在内存中存储,由于需要以%u输出,所以需要进行整型提升符号位为1所以补1.,得到补码为11111111111111111111111110000000,由于需要以%u输出,所以它是无符号类型,所以原码反码补码相同都是11111111111111111111111110000000,故答案为4294967168。

5.大轮盘理解

对于char由于它是只有8个bite位所有最大为11111111.它的具体数值我们可以画图来了解

我们可以进一步得到:

在signed char类型中

进一步得到

在int short long 类型和这相似,想要研究的小伙伴可以自行计算。

6.浮点家族

7.IEEE标准

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

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

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

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

2^E表示指数位。

IEEE 754规定:

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

对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M

例如10进制的5.5转化为二进制为101.1=(-1)^0*1.011*2^2;

S=0 M=1.011 E=2;

E为一个无符号整数(unsigned int)

这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们

知道,科学计数法中的E是可以出

现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127.

所以存储时S=0  E=10000001 M =01100000000000000000000

故在内存中以0 10000001 01100000000000000000000

8.练习

学到这里我们看一下代码

#include <stdio.h>
int main()
{
  int a = 9;
  float* p = (float*)&a;
  printf("%d\n",a);
  printf("%f\n", *p);
  *p = 9.0;
  printf("%d\n", a);
  printf("%f\n", *p);
  return  0;
}

       在printf("%d\n",a);中毫无疑问是9,对于*p由于在存储时是二进制为00000000000000000000000000001001,由于是浮点型 S=0 E=00000000 M=00000000000000000001001 E=0-127=-127,故(-1)^S * M * 2^E为0;

10进制为9.0二进制为1001.0=(-1)^0*1.001*2^3;

S=0 M=1.001 E=3+127=130;故为0 1000 0010 00100000000000000000000;

   printf("%f\n", *p);为9.000000;

到这里我们今天的内容就结束了,内容制作不易,希望大家可以一键三连。

目录
相关文章
|
22天前
|
监控 算法 应用服务中间件
“四两拨千斤” —— 1.2MB 数据如何吃掉 10GB 内存
一个特殊请求引发服务器内存用量暴涨进而导致进程 OOM 的惨案。
|
21天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
44 1
|
26天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
28天前
|
监控 Java easyexcel
面试官:POI大量数据读取内存溢出?如何解决?
【10月更文挑战第14天】 在处理大量数据时,使用Apache POI库读取Excel文件可能会导致内存溢出的问题。这是因为POI在读取Excel文件时,会将整个文档加载到内存中,如果文件过大,就会消耗大量内存。以下是一些解决这一问题的策略:
67 1
|
30天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
1月前
|
缓存 安全 Java
使用 Java 内存模型解决多线程中的数据竞争问题
【10月更文挑战第11天】在 Java 多线程编程中,数据竞争是一个常见问题。通过使用 `synchronized` 关键字、`volatile` 关键字、原子类、显式锁、避免共享可变数据、合理设计数据结构、遵循线程安全原则和使用线程池等方法,可以有效解决数据竞争问题,确保程序的正确性和稳定性。
36 2
|
1月前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
41 4
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
53 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
4月前
|
存储 分布式计算 Hadoop
HadoopCPU、内存、存储限制
【7月更文挑战第13天】
279 14
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
366 0