【C语言】浮点型数据在内存中的存储

简介: ⭐浮点数在内存中的存储float、double、long double浮点数的范围定义在float.h头文件中

⭐浮点数在内存中的存储

float、double、long double

浮点数的范围定义在float.h头文件中

1.1 🤓举个例子:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
  int num = 5;
  float* pfloat = (float*)&num;
  printf("num的值为:%d\n", num);
  printf("*pFloat的值为:%f\n", *pfloat);
  *pfloat = 9.0;
  printf("num的值为:%d\n", num);
  printf("*pFloat的值为:%f\n", *pfloat);
  return 0;
}

输出结果

0f59c5901c6f46a0a2251ad071111d09.png

这里肯定会有小伙伴好奇,int于float都是四个字节,为什么只是改变&num的指针类型,用%d的方式取出来值没有变化,用%f读取出来 * pfloat的值也就是num的数值会是0??而用浮点数给 * pfloat重新赋值用%d打印又不对,用%f打印出来又正常。


我们都知道改变了指针类型,里面的二进制数据是不会变的,只不过读取大小和读取方式有区别,而int于float又都是四个字节,那就证明,浮点型的存取方式与整形不相同。

1.2浮点数存储规则🌈:

如果说浮点数与整数在内存中的存取方式不相同,那么浮点数的存储规则是什么呢 ?

实际上浮点数是以科学计数法的方式存储在内存中

  • (-1)^ S * M * 2^E (// 此处的^均代表指数,而不是异或)
  • S代表符号位,由于内存中存储的是二进制所以S只有0和1,0代表正数(-1的0次幂为1),1代表负数(-1的1次幂为-1)
  • M代表有效数字 大于1小于2
  • E代表 2的指数位

🌞IEEE 754标准规定,32位浮点数最高的1位是符号位s,接下来8位是指数E,剩下的23位为M.

0640e12131db48358b3ee362d9edc8a4.png

64位浮点数最高的1位是符号位s,接下来11位是指数E,剩下的52位为M。

b0129a9744cc43c08f0e6d0141fbd2ec.png

对于M与E有一些特别规定

标准规定,对于M,由于一定是1.XXXXX,所以可以舍去第一位,取出的时候加上即可,所以存在M中的数据就是1.后面的数字,这样做可以节省一位数字,虽然M只有23位,但是节省一位之后就可以存储相当于24位的数字了。

对于E,E是一个无符号整数,拿单精度浮点型float举例,E为8位,所以它的取值范围为0-255,但是科学计数法中E是可以出现负数的,,所以IEEE754标准规定,存入内存时E必须加上一个中间数,对于八位的E,这个中间数是127,对于11位的E这个中间数是1023,比如单精度E为10,那么在存储的时候,将E加上127,保存在内存中就是10001001。

以上为E的存储情况,E取出的时候还分为三种情况:

E不为全0或者不为全1

这时浮点数采用下面的规则,指数E减去127(或者1023),得到真实E的值,再将M的前面加回第一位的1.

E为全0

这时,浮点数的指数E=1-127(或者1-1023)就是真实值

有效数字M不再加上前面的第一位1,这样做是为了表示±0,就是一个接近于0的一个很小的数字

E为全1

相当于±无穷大(对于float本身来说)

ps:

实际上浮点数是以科学计数法的方式存储在内存中,S、E、M是科学计数法的不同部分


比如存储一个float类型110.75,计算机中存储的是二进制,转化为二进制数据1101110.11用科学计数法就表示为1.10111011*2^6


其中 符号就代表了S,S=0,1.10111011代表了M,6代表了E,八位二进制为00000110,将E加上127,将m去掉第一位1,所以这个数据存储在内存中应该就是0100 0010 1101 1101 1000 0000 0000 0000,转化为16进制为42DD 8000

让我们验证一下:

38fbbeee67f24f7abd6ece6a8208778d.png

完全正确✨,至于数据为什么是倒着存,这就涉及到大小端字节序问题,请参考这篇博文http://t.csdn.cn/mHrtN

1.3解释前面题目:

int main()
{
  int num = 5;
  float* pfloat = (float*)&num;
  printf("num的值为:%d\n", num);       //5
  printf("*pFloat的值为:%f\n", *pfloat);   //0.000000
  *pfloat = 9.0;
  printf("num的值为:%d\n", num);       //1091567616
  printf("*pFloat的值为:%f\n", *pfloat);   //9.000000
  return 0;
}
  • 为什么num 为5,&num转换为浮点型指针就变成了0.000000? 🧐

5的二进制 00000000 00000000 00000000 00000101

转换为浮点型指针进行读取,采用浮点型的规定去读,此时在浮点型看来

98bdf81c088242e2858eb81fb065bd6b.png

-1)^ S * M * 2 ^ E = (-1)^ 1 * 0.000000000000000000000101 * 2 ^ (1-127) ( 因为E全为0,参考上面E全为0取出。)

得到一个超级小的数字,对于float来说就根无穷小没有区别,截断等于0.000000。

  • 为什么对*pfloat赋值9.0,用%d输出是1091567616?🤓

将9.0的二进制是1001 科学技术法 1.001*2^3 S=0,E=3,M=1001

用float的方式存储就是 0 10000010 00100000000000000000000

用%d的方式输出,也就是用整数方式把数据读取出来,结果就是1091567616

f39fcb55b21a4afa8fa846c398447023.png

最后的pfloat = 9.0用%f输出,用浮点型方式存,用浮点型方式取,自然就是9.000000了。

完结

创作不易,还请各位小伙伴多多点赞👍关注✨收藏⭐




9c0d694f9836430aa61f1b9169edf136.gif


































相关文章
|
19天前
|
存储 程序员 编译器
C 语言中的数据类型转换:连接不同数据世界的桥梁
C语言中的数据类型转换是程序设计中不可或缺的一部分,它如同连接不同数据世界的桥梁,使得不同类型的变量之间能够互相传递和转换,确保了程序的灵活性与兼容性。通过强制类型转换或自动类型转换,C语言允许开发者在保证数据完整性的前提下,实现复杂的数据处理逻辑。
|
19天前
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
31 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
20天前
|
存储 数据管理 C语言
C 语言中的文件操作:数据持久化的关键桥梁
C语言中的文件操作是实现数据持久化的重要手段,通过 fopen、fclose、fread、fwrite 等函数,可以实现对文件的创建、读写和关闭,构建程序与外部数据存储之间的桥梁。
|
22天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
40 6
|
23天前
|
存储 数据建模 程序员
C 语言结构体 —— 数据封装的利器
C语言结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起,形成一个整体。它支持数据封装,便于管理和传递复杂数据,是程序设计中的重要工具。
|
29天前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
101 13
|
29天前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
57 11
|
23天前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
29天前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
52 11
|
21天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
49 1