当前位置: 首页 > article >正文

高阶C语言|深度剖析数据在内存中的存储

文章目录

      • 重点
      • 1. 数据类型介绍
        • 1.1 数据类型的基本分类
      • 2. 整型在内存中的存储
        • 2.1 原码、反码、补码
        • 2.2 大小端字节序
        • 2.3 判断字节序
      • 3. 浮点型在内存中的存储
        • 3.1 IEEE 754 浮点数标准
        • 3.2 浮点数与整数的内存存储差异
        • 3.3 浮点数存储示例
      • 4. 实战练习
      • 总结

💬 欢迎讨论:在阅读过程中有任何疑问,欢迎在评论区留言,我们一起交流学习!

👍 点赞、收藏与分享:如果你觉得这篇文章对你有帮助,记得点赞、收藏,并分享给更多对数据存储感兴趣的朋友!

重点

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

1. 数据类型介绍

在计算机程序中,数据类型不仅决定了变量存储数据的方式,还决定了如何高效地处理这些数据。每种数据类型都有其特定的内存分配规则、范围和使用场景。理解数据类型的基本分类是学习内存存储的第一步。

1.1 数据类型的基本分类
  • 整型家族:用于表示整数值。

    • char:字符类型,通常占 1 字节。用于表示字符或小范围整数。
    • short:短整型,占 2 字节,范围通常为 -32,768 到 32,767。
    • int:整型,占 4 字节,范围通常为 -2,147,483,648 到 2,147,483,647。
    • long:长整型,占 4 或 8 字节(平台依赖),在 64 位系统中通常为 8 字节。
    • long long:更长的整型,占 8 字节,适用于存储更大的整数。
  • 浮点型家族:用于表示带小数点的数字,适用于处理实数。

    • float:单精度浮点数,占 4 字节,提供大约 6 位有效数字的精度。
    • double:双精度浮点数,占 8 字节,提供大约 15 位有效数字的精度。
    • long double:扩展精度浮点数,占 12 或 16 字节,具体取决于平台,提供更高精度。
  • 其他类型

    • void:空类型,用于表示函数的返回类型或无类型的指针。
    • 指针类型:用于存储变量的地址,常见类型有 int*char*float* 等。

这些数据类型的选择不仅影响变量占用的内存大小,还影响程序的性能和计算精度。熟悉不同类型的内存存储规则是理解程序如何高效运行的基础。


2. 整型在内存中的存储

计算机内存以二进制的方式存储数据,整型(如 intshort 等)采用不同的编码方式来表示数值。常见的表示方法有 原码反码补码

2.1 原码、反码、补码
  • 原码:直接将数值按符号位和数值位转换成二进制。对于负数,符号位为 1,正数的符号位为 0

  • 反码:对原码中的数值位取反,符号位不变。反码的主要用途是对负数进行运算。

  • 补码:反码加 1,计算机使用补码来表示负数。补码的使用使得加法器能够统一处理正负数的加法,简化了硬件设计。

在计算机内存中,整数通常以补码形式存储,因为补码运算能够简化加减运算,同时避免了负数处理的复杂性。通过补码,可以实现更高效的运算,并且不需要额外的硬件支持。

2.2 大小端字节序

计算机存储数据时,字节的排列顺序并非一成不变。根据字节存储的高低位顺序,计算机系统有两种常见的字节序:大端字节序小端字节序

  • 大端字节序(Big-endian):将数据的高位字节存储在内存的低地址处,低位字节存储在高地址处。例如,对于一个 32 位的整数 0x11223344,大端存储方式将其存储为:

    地址:0x00  0x01  0x02  0x03  
    数据:  0x11  0x22  0x33  0x44
    
  • 小端字节序(Little-endian):将数据的低位字节存储在内存的低地址处,高位字节存储在高地址处。例如,同样是 0x11223344,小端存储方式将其存储为:

    地址:0x00  0x01  0x02  0x03  
    数据:  0x44  0x33  0x22  0x11
    

不同的计算机体系结构可能采用不同的字节序。例如,x86 架构采用小端字节序,而某些老式的 RISC 架构或网络协议则使用大端字节序。

2.3 判断字节序

以下是一个简单的 C 程序,可以判断当前系统使用的是大端字节序还是小端字节序:

#include <stdio.h>

int check_endian() {
    int num = 1;
    return (*(char *)&num == 1);
}

int main() {
    if (check_endian()) {
        printf("小端字节序\n");
    } else {
        printf("大端字节序\n");
    }
    return 0;
}

该程序通过查看整数 1 在内存中的存储情况来判断字节序。如果 1 的最低有效字节(LSB)存储在低地址,则为小端字节序,否则为大端字节序。


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

浮点数用于表示实数(带小数的数字),在计算机内部采用 IEEE 754 标准 进行存储。该标准规定了浮点数如何用二进制表示,包括符号位、指数位和尾数部分。

3.1 IEEE 754 浮点数标准

浮点数的表示形式为:
[
(-1)^S \times M \times 2^E
]
其中:

  • S:符号位,0 表示正数,1 表示负数。
  • M:尾数(有效数字),大于等于 1 小于 2。
  • E:指数,表示数据需要乘以 2 的多少次方。

对于 32 位的单精度浮点数:

  • 符号位:1 位
  • 指数位:8 位(无符号整数,使用偏移量 127)
  • 尾数位:23 位(有效数字,去除前导 1)

对于 64 位的双精度浮点数:

  • 符号位:1 位
  • 指数位:11 位(使用偏移量 1023)
  • 尾数位:52 位

浮点数的精度和范围受限于其表示位数。由于尾数部分只能表示有限的有效数字,因此浮点数在计算时可能会出现舍入误差。

3.2 浮点数与整数的内存存储差异

浮点数和整数在内存中的存储方式不同,可能导致同一段内存数据被不同类型解读时出现巨大差异。例如:

int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n", n);          // 输出:9
printf("*pFloat的值为:%f\n", *pFloat);  // 输出:9.000000

在内存中,整数和浮点数使用不同的格式存储,导致相同的内存内容可能被解读为不同的数值。

3.3 浮点数存储示例

以浮点数 9.0 为例,它在 IEEE 754 单精度浮点数格式中的存储过程如下:

  1. 9.0 转化为二进制表示:1001.0,即 1.001 × 2^3
  2. 符号位:S = 0(正数)
  3. 指数位:E = 3 + 127 = 130(偏移量 127)
  4. 尾数位:M = 00100000000000000000000(去除前导 1,保留 23 位)

因此,9.0 在内存中的 32 位表示为:

符号位 | 指数位 | 尾数位
0      | 10000010 | 00100000000000000000000

通过这种方式,计算机可以

在内存中高效存储浮点数。


4. 实战练习

通过实际编程练习,可以加深对内存存储原理的理解:

  1. 练习1:打印 char 类型的溢出情况,观察 char 类型从 -128127 的范围如何影响存储。
  2. 练习2:手动实现整数到二进制(补码)的转换,并观察不同符号的存储效果。
  3. 练习3:在小端和大端机器上分别存储 intfloat 类型的变量,查看它们在内存中的表现。
  4. 练习4:使用位运算检查浮点数的存储结构,深入理解其表示方式。

总结

通过对数据类型、整数和浮点数在内存中存储方式的深入理解,可以更清楚地看到计算机如何高效地处理不同类型的数据。掌握补码、大端字节序、浮点数表示等基本概念,将有助于我们在编程中避免潜在的错误和性能瓶颈。


http://www.kler.cn/a/454986.html

相关文章:

  • 【QED】等式构造
  • Docker 开启远程端口访问2375
  • 如何增加多行内容到文件
  • 深度学习在自动驾驶车辆车道检测中的应用
  • ES7+ React/Redux/GraphQL/React-Native snippets 使用指南
  • Linux 下处理 ^M 字符的最佳实践
  • RestTemplate关于https的使用详解
  • 编译openssl遇到错误Parse errors: No plan found in TAP output的解决方法
  • PyTorch Lightning Callback介绍
  • 如何设置爬虫的User-Agent?
  • java实现网络IO高并发编程java NIO
  • 在uniapp中如何自定义一个图标
  • 【软件工程】十万字知识点梳理 | 期末复习专用
  • docker mysql5.7安装
  • .net core 的软件开发模式
  • 欲海航舟:探寻天性驱动下的欲望演变与人生驾驭
  • ArcGIS土地利用数据制备、分析及基于FLUS模型土地利用预测(数据采集、处理、分析、制图)
  • Python数据可视化小项目
  • 【Redis】Redis 安装与启动
  • Go 计算Utf8字符串的长度 不要超过mysql字段的最大长度
  • springboot502基于WEB的牙科诊所管理系统(论文+源码)_kaic
  • Linux知识点回顾(期末提分篇)
  • 文档大师:打造一站式 Word 报告解决方案1
  • Java实现观察者模式
  • 同步与异步日志系统的深入探讨与应用
  • 箭头函数与普通函数的区别