news 2026/8/15 13:59:49

数据的存储

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据的存储
标题

目录

数据存储

整数在内存中的存储

存储规则

机器码

大小端字节序以及其判断

浮点数在内存中的存储


数据存储

整数在内存中的存储

存储规则

计算机内部使用二进制编码表示整数,带符号的整数称为机器数(包含符号位和数值位),实际数值是真值。

符号位数值位
0为正,1为负数的绝对值

机器码

整数的二进制表示方法有三种,即原码、反码、补码。

正整数的原码、反码、补码相同。

负整数:

  • 原码为将数值按照正负数的形式翻译为二进制形式得到的数值码。
  • 反码为原码的符号位不变,数值位按位取反。
  • 补码为反码加一。

在计算机中,统一采用补码的存储及运算。

计算机硬件中只有加法器,补码可以将符号位和数值域统一处理,减法运算转换为加法运算,简化了运算器的设计,不需要额外的硬件电路。

大小端字节序以及其判断

概念

如下图所示,在vs调试当中,我们取地址a,可以发现它是按照字节为单位倒着存储的。

那下面我们一起来探讨一下数据在内存中存储顺序的问题。

在计算机中,内存的编制是由字节组成的,一个多字节的数据会占用连续多个字节。

按照不同的存储顺序,我们分为大端模式小端模式

大端存储
数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存
在内存的低地址处。
小端存储
数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存
在内存的⾼地址处。
  • 大端字节序常用于:网络协议、嵌入式、单片机。
  • 小端字节序常用于:x86 架构 PC、Windows、Linux(日常电脑都是小端)。

练习1

利用大小端字节序的概念,设计一个简单的程序判断当前机器的字节序。

int check_order() { int i = 1; return (*(char*)&i); } int main() { int ret = check_order(); if (ret == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }

代码解析:

  • 定义 int i=1,整形为4个字节,在二进制编码当中为
00 00 00 01

高字节为: 00 00 00

低字节为: 01

  • 取变量 i 的低地址,将其强制转换为char类型,只读取1个字节,并解引用,取出第一个字节的值。

主函数判断

内存低地址 → 高地址 01 00 00 00

返回值为1,为小端。

高字节 → 低地址 00 00 00 01

返回值为0,为大端。

练习2

int main() { char a = -1; signed char b = -1; unsigned char c = -1; printf("%d,%d,%d\n", a, b, c); return 0; }

运行结果如下:

代码解析:

由于打印格式为%d需要整形提升

提升规则:

  1. 有符号数:按符号位扩展(高位补符号位)
  2. 无符号数:高位补0
  • a的原码: 10000000 00000000 00000000 00000001

反码: 111111111 111111111 111111111 111111110

补码: 111111111 111111111 111111111111111111

内存补码为11111111

提升后补码为 111111111 111111111 111111111 111111111 ,真值为-1。

  • 同理,b打印也为-1。
  • 同理,c的内存存储为11111111

提升后补码为00000000 00000000 00000000 111111111,真值为255。

练习3

int main() { char a = -128; printf("%u\n", a); return 0; }
  • %u为无符号数打印形式
  • a为char类型需要整型提升
-128 原码 -> 10000000 00000000 00000000 10000000 反码 -> 11111111 11111111 11111111 01111111 补码 -> 11111111 11111111 11111111 10000000 内存存储 -> 10000000 整型提升 -> 11111111 11111111 11111111 10000000

结果如下图所示:

练习4

int main() { char a = 128; printf("%u\n", a); return 0; }

结果如下图所示:

练习5

#include <string.h> int main() { char a[1000]; int i; for ( i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%zd", strlen(a)); return 0; }
  • 求数组a的字符串长度-> 在‘\0’(0)前的字符串长度
  • -1-i为依次-1的循环模式,范围为-1 -> -128 -> 127-> 0

结果如下图所示:

练习6

unsigned char i = 0; int main() { for(i = 0; i <=255; i++) { printf("hello world\n"); } return 0; }
  • 代码结果为无限循环。
  • 无符号数的取值范围为0~255。
  • 如果数值大于255(二进制为11111111),增一为100000000,取八位为00000000,即返回0。

练习7

#include <Windows.h> int main() { unsigned int i; for (i = 9; i >= 0; i--) { printf("%u\n",i); Sleep(1000); } return 0; }
  • 代码结果为无限循环。
  • 无符号整数的取值范围很大,为0-32位的1组成的数。
  • 所以 i>=0 的判断恒成立,程序会无限循环。

结果如下图所示:

练习8

int main() { int a[4] = { 1,2,3,4 }; int* ptr1 = (int*)(&a + 1); int* ptr2 = (int*)((int)a + 1); printf("%x,%x\n", ptr1[-1], *ptr2); return 0; }

如图所示:

地址偏移(字节): 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 对应元素: ───── a[0]=1 ────┼───── a[1]=2 ────┼───── a[2]=3 ────┼───── a[3]=4 ────┼ 数组外未知内存 字节归属: 0~3号字节 4~7号字节 8~11号字节 12~15号字节 16号及以后
ptr1: a 表示数组首元素的地址 &a 表示整个数组的地址 &a+1 表示跳过整个数组 (int*)(&a+1)即ptr1 解引用表示一个数组的单个元素 ptr1[-1] 即为4
偏移: 0 ... 15 16 ↑ ↑ &a ptr1 (&a+1 的位置) 偏移: 12 13 14 15 | 16 ↑ ↑ a[3]=4 ptr1 (ptr1 - 1)
ptr2: (int)a 表示将a强制转换为普通整数 (int)a+1 纯数值 +1,只偏移 1 个字节 再强制转回 int*,得到 ptr2
偏移: 0 1 2 3 ↑ ↑ a ptr2 a[0]首字节 a[0]第2字节

结果如下图所示:

浮点数在内存中的存储

基础划分

类型总位数符号位 (S)阶码 (E)尾数 (M)
float(单精度)32 bit1 bit8 bit23 bit
double(双精度)64 bit1 bit11 bit52 bit

内存布局(高位 → 低位):符号位 S + 阶码 E + 尾数 M

存储规则

浮点数在计算机内部的表示方法:

  • S表示符号位,0为正数,1为负数。
  • M表示有效数字,区间为1<=M<2。
  • E为指数位。

存储过程

浮点数存放
有效数字M
  • 约定:二进制浮点数整数部分固定为 1,所以可以被舍去,只存小数部分,写作1.M。
  • 这一步叫隐藏整数 1,可以节省 1 位空间。
指数E
  • 规定:E是一个无符号整数。但在科学计数法中,E可以有负数的形式出现。
  • 所以当存入内存时,指数E需要将原有的真实值加上一个中间数。
  • 对于8位的E,取值范围为0-255,中间数位127。
  • 对于11位的E,取值范围为0-2047,中间数位1023。
浮点数取值
规格化浮点数
  • E不为全0或不为全1
指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第⼀位的1。
非规格化浮点数
  • E为全0

将隐藏的整数 1 取消,小数变为 0.M。表⽰±0,以及接近于0的很小的数字。

  • E为全1
如果有效数字M全为0,表⽰±无穷⼤(正负取决于符号位s)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/15 13:59:26

免费开源的桌面围栏工具NoFences:3分钟让图标各归其位

免费开源的桌面围栏工具NoFences&#xff1a;3分钟让图标各归其位 【免费下载链接】NoFences &#x1f6a7; Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences NoFences 是一款免费开源的 Windows 桌面整理工具&#xff…

作者头像 李华
网站建设 2026/8/15 13:56:22

微信聊天记录存哪里才安心?WeChatMsg 本地留档实操手册

微信聊天记录存哪里才安心&#xff1f;WeChatMsg 本地留档实操手册 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeCh…

作者头像 李华
网站建设 2026/8/15 13:55:34

面试官:Workflow 和 Agent 有什么区别?如何选型?

近一年来&#xff0c;各类 Agent 产品集中爆发。为了体现技术先进性&#xff0c;许多接入了大模型的应用都将自己定义为「Agent」。 但在实际使用中你会发现&#xff0c;很多号称 Agent 的系统&#xff0c;底层仍然是传统的自动化流程。它们的步骤是固定的&#xff0c;路径是预…

作者头像 李华
网站建设 2026/8/15 13:54:37

一篇搞定 OneNote 笔记迁移:onenote-md-exporter 完整使用指南

一篇搞定 OneNote 笔记迁移&#xff1a;onenote-md-exporter 完整使用指南 【免费下载链接】onenote-md-exporter ConsoleApp to export OneNote notebooks to Markdown formats 项目地址: https://gitcode.com/gh_mirrors/on/onenote-md-exporter 你是不是也有这样一天…

作者头像 李华
网站建设 2026/8/15 13:53:03

AIGC无限画布前端实现:从Canvas架构到性能优化全解析

1. 项目概述&#xff1a;为什么我们需要一个“无限画布”&#xff1f; 如果你最近也在玩各种AI绘画工具&#xff0c;大概率会遇到一个共同的痛点&#xff1a;画布尺寸是固定的。你想画一个宏大的场景&#xff0c;或者想把几个独立的创意串联成一个故事板&#xff0c;却发现画布…

作者头像 李华
网站建设 2026/8/15 13:52:32

QQ空间备份三步走:用QQ空间导出助手免费永久保存十年青春

QQ空间备份三步走&#xff1a;用QQ空间导出助手免费永久保存十年青春 【免费下载链接】QZoneExport QQ空间导出助手&#xff0c;用于备份QQ空间的说说、日志、私密日记、相册、视频、留言板、QQ好友、收藏夹、分享、最近访客为文件&#xff0c;便于迁移与保存 项目地址: http…

作者头像 李华