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

第19讲:数据在内存中的存储

📚 第19讲:数据在内存中的存储 💾

从“0”和“1”开始,揭开计算机记忆的秘密!


📂 目录

  1. 整数在内存中的存储 —— 补码的暗号系统
  2. 大小端字节序 —— 字节的排队方式
  3. 浮点数在内存中的存储 —— 科学计数法的特工编码

📖 正文开始

我们每天写 int a = 5;,但你有没有想过:

“5” 这个数字,真的在内存里写了个“5”吗?
为什么 -1 变成 unsigned 后,突然变成了 255
为什么 9 当成 float 读,会变成 0.000000

别急,我们一个一个“破案”,还会运行真实代码,亲眼见证“内存魔术”!


整数在内存中的存储 —— 补码的暗号系统 🔐

🌟 生活比喻:银行的“负数账户”

想象你去银行开户:

  • 存了 5 元 → 记账:+5
  • 欠了 5 元 → 银行不会写 -5,而是用一种“暗号”来记账。

这个“暗号系统”就是 补码(Two’s Complement)
计算机世界里,所有整数都用补码存储


🔹 三种“暗号”形式

类型规则
原码直接翻译成二进制,符号位为1表示负数
反码符号位不变,其余位取反
补码反码 + 1
✅ 示例:-5 的表示(8位)
原码:   1000 0101  ← 符号位1,数值101
反码:   1111 1010  ← 符号位不变,其余取反
补码:   1111 1011  ← 反码 + 1

✅ 正整数的原、反、补码都相同!


🔧 为什么用补码?—— 因为CPU只有“加法器”!

想象你家孩子想算:5 - 3 = ?
但你家的计算器只有“+”按钮,没有“-”按钮。怎么办?

聪明的办法:
-3 编码成一个“特殊数字”,让 5 + (这个数字) = 2
这个“特殊数字”就是 -3 的补码

✅ 示例代码:验证补码加法
#include <stdio.h>int main() {int a = 5;int b = -3;printf("5 + (-3) = %d\n", a + b);  // 输出:2return 0;
}

✅ 虽然你写了减法,但CPU底层是用“加法器”完成的!


大小端字节序 —— 字节的“排队方式” 🚶‍♂️🚶‍♀️

🌟 生活比喻:快递包裹的打包方式

假设你要寄一个大箱子,里面有4个小包裹:11223344
但快递公司规定:必须按字节存放

问题来了:

你是把“大号包裹”放前面,还是“小号包裹”放前面?

这就引出了两种“打包规则”:

打包方式描述
大端模式高位字节 → 低地址 低位字节 → 高地址
小端模式低位字节 → 低地址 高位字节 → 高地址

🔍 真实代码观察:内存中的“倒序”

#include <stdio.h>int main() {int a = 0x11223344;  // 十六进制数return 0;
}

🔍 调试时你会发现:内存中存储的是 44 33 22 11 —— 倒着存的

这就是 小端模式 的典型特征!
我们常用的 x86 电脑就是小端模式。


✅ 如何判断你的电脑是“左撇子”还是“右撇子”?

方法一:指针法(经典)
#include <stdio.h>int check_sys() {int i = 1;return (*(char *)&i);  // 取第一个字节
}int main() {if (check_sys() == 1) {printf("小端\n");  // 小端:低字节在低地址} else {printf("大端\n");}return 0;
}

✅ 输出:小端


方法二:联合体法(更直观)
int check_sys() {union {int i;char c;} un;un.i = 1;return un.c;  // 共享内存,直接读char部分
}

✅ 两种方法殊途同归!


🧩 综合练习与代码解析

🔹 练习2:char 的“身份危机”
#include <stdio.h>
int main() {char a = -1;signed char b = -1;unsigned char c = -1;printf("a=%d, b=%d, c=%d\n", a, b, c);return 0;
}

📌 输出:a=-1, b=-1, c=255

🔍 解析

  • a, b:有符号,-1 的补码 11111111 解释为 -1
  • c:无符号,11111111 解释为 255

🔹 练习3:负数转无符号
#include <stdio.h>
int main() {char a = -128;printf("%u\n", a);  // 输出:4294967168return 0;
}

🔍 过程

  1. char a = -128 → 补码 10000000
  2. 整型提升 → 11111111 11111111 11111111 10000000
  3. %u 打印 → 无符号整数:4294967168

🔹 练习4:strlen 与字符范围
#include <stdio.h>
#include <string.h>
int main() {char a[1000];int i;for(i = 0; i < 1000; i++) {a[i] = -1 - i;}printf("%d\n", strlen(a));  // 输出:255return 0;
}

🔍 解析

  • char 范围:-128 ~ 127
  • a[255] = -1 - 255 = -256 ≡ 0 mod 256\0
  • 前255个都不是 \0,所以 strlen 返回 255

🔹 练习5:无符号循环陷阱
#include <stdio.h>
unsigned char i = 0;
int main() {for(i = 0; i <= 255; i++) {printf("hello world\n");  // 死循环!}return 0;
}

⚠️ 警告iunsigned char,最大 255i++ 后会回绕到 0,永远满足 i <= 255无限循环


🔹 练习6:指针运算(X86 小端)
#include <stdio.h>
int main() {int a[4] = {1, 2, 3, 4};int *ptr1 = (int *)(&a + 1);           // 指向数组末尾后int *ptr2 = (int *)((char *)a + 1);    // 从首地址偏移1字节printf("%x,%x\n", ptr1[-1], *ptr2);    // 输出:4,2000000return 0;
}

🔍 解析

  • ptr1[-1]a[3]4
  • a[0] = 1 = 0x00000001(小端:01 00 00 00
  • 从第2字节开始读 int00 00 00 02?不对
  • 实际:00 00 00 + 下一个 int 的第1字节 0202 00 00 000x2000000

答案4,2000000


浮点数在内存中的存储 —— 科学计数法的“特工编码” 🕵️‍♂️

🌟 生活比喻:科学家的“极简记账法”

科学家写数字从不写 9.0,而是写:1.001 × 2³
IEEE 754 就是把这种写法“编码”成二进制。

✅ IEEE 754 公式:

V=(−1)S×M×2EV=(−1)S×M×2E

字段含义
S符号位:0 正,1
M有效数字,1 ≤ M < 2
E指数(阶码)

🔧 存储时的“压缩技巧”

技巧1:省掉“1.”

M = 1.001 → 存的时候只存 .001,读的时候再加回来。

就像你写“1米5”省略“1”,别人知道是“1.5米”。

技巧2:指数加“偏移量”
E = 3` → 存 `3 + 127 = 130

因为内存里不能存负数!
就像温度计:-5°C 实际记录为 268(假设偏移273)


🔍 经典谜题破解:intfloat 的“身份互换”

#include <stdio.h>
int main() {int n = 9;float *pFloat = (float *)&n;printf("n的值为:%d\n", n);           // 9printf("*pFloat的值为:%f\n", *pFloat); // 0.000000*pFloat = 9.0;printf("n的值为:%d\n", n);           // 1091567616printf("*pFloat的值为:%f\n", *pFloat); // 9.000000return 0;
}

🔍 第一环节9 当作 float

  • E 全为0 → 特殊情况,M 前面是 0. → 数值极小 → 0.000000

🔍 第二环节9.0 存入,int 读出

  • 9.0 = 1.001 × 2³E=130, M=001...
  • 二进制:0 10000010 00100000000000000000000
  • 当成整数读:1091567616

🎯 总结:三张“记忆卡片” 🃏

卡片核心要点
整数所有整数都用补码存储,负数的“暗号”让CPU只用加法器
大小端小端:低字节在低地址(x86常见) 大端:高字节在低地址(网络协议常见)
浮点数IEEE 754:S(正负)、E(指数+127)、M(省掉1.)

🎯 恭喜你!
你现在不仅能写代码,还能看懂内存中的“0”和“1”在说什么!

http://www.dtcms.com/a/497100.html

相关文章:

  • 湛江企业建站程序竞价网站托管
  • 做网站网站代理怎么找客源贵阳网站建设多少钱
  • 商城网站建设论坛买正品东西哪个网最好
  • 网站关键词排名快速提升长春做网站wang
  • 建筑焊工证查询网站官方网国家信用信息公示系统山东
  • 网站统计模块深圳中高风险地区
  • 哪家做网站好 成都php网站 源码
  • 网站读取速度慢提高网站响应速度
  • HDI电路板的阶数
  • 网站建设培训多少钱婚庆5个坑
  • 网站备案 加急网推技巧
  • 个人网上银行登录官网丰台网站关键词优化
  • 基于SpringBoot的“中学信息技术课程教学网站”的设计与实现(源码+数据库+文档+PPT)_2025-10-17
  • 深圳做营销网站公司哪家好长沙系统开发公司
  • 青州建设局网站沈阳网站制作找网势科技
  • 多个招聘网站格式不一致如何做招聘记录常平网站仿做
  • 招聘网站建设规划书C语言网站开发pdf
  • net网站开发技术方案欣赏艺术类的网站
  • Python类的高级特性:__new__ 和 __init_subclass__
  • html5手机微网站亚洲长尾关键词挖掘
  • 政务网站建设标准附近卖建筑模板市场
  • 【小学教辅】25新二年级上册语文阅读理解每日一练 小学二年级语文阅读理解专项练习 二年级上册语文每日练习题 电子版可下载打印|夸克网盘
  • 做服装网站宣传明星网页制作模板
  • 智慧旅游网站建设方案ppt模板wordpress 数据库同步
  • MATLAB 疑难问题诊疗:从常见报错到深度优化的全流程指南
  • 用什么软件做动漫视频网站wordpress企业网站模板下载
  • 保定网站建设旅游网站系统设计与开发
  • 四川平台网站建设设计百度关键词seo排名
  • 网站开发过程淘客WordPress主题
  • 哪个网站可以做竖屏网站的模版可以换吗