【C语言系列】数据在内存中存储
数据在内存中存储
- 一、整数在内存中的存储
- 二、大小端字节序和字节序判断
- 2.1什么是大小端?
- 2.2练习
- 2.2.1练习1
- 2.2.2练习2
- 2.2.3练习3
- 2.2.4练习4
- 2.2.5练习5
- 2.2.6练习6
- 三、浮点数在内存中的存储
- 3.1练习
- 3.2浮点数的存储
- 3.2.1 浮点数存的过程
- 3.2.2 浮点数取的过程
- 3.3题目解析
- 四、总结
- 4.1整数在内存中的存储
- 4.2大小端字节序
- 4.3浮点数在内存中的存储
- 4.4总结
一、整数在内存中的存储
整数的2进制表示方法有三种,即原码、反码和补码。
有符号整数,符号位 0 —— 正 1 —— 负,最高位为符号位
正整数的原、反、补码都相同。
负整数的三种表示方法各不相同,如下:
原码:直接被数值按照正负数的形式翻译成二进制得到的是原码。
反码:将原码的符号位不变,其他位次按位取反,就得到了反码。
补码:反码+1就得到补码。
注:对于整形来说:数据存放内存中其实存放的是二进制补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。 原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
二、大小端字节序和字节序判断
当我们了解了整数在内存中存储后,我们调试看一个细节:
int main()
{
int n = 0x11223344;
return 0;
}
调试结果如下图:

注:
1.整数在内存中存储的是二进制的补码。
2.在调试窗口中观察内存的时候,为了方便展示,显示的是16进制的值。
3.存储的顺序是倒过来的!
进行调试后,观察上述图片我们可以看到n中的 0x11223344 这个数字是按照字节为单位,倒着存储的。这是为什么呢?
2.1什么是大小端?
x86 —— 小端模式(DSP) KEIL C51 —— 大端模式
其实超过一个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储。
大端字节序存储:把一个数据的低位字节的内容存储到高地址处,把高位字节的内容存储到低地址处。
小端字节序存储:把一个数据的低位字节的内容存储到低地址处,把高位字节的内容存储到高地址处。
如下图:

为什么有大小端模式之分?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit 位,但是在C语言中除了8 bit 的char 之外,还有16 bit 的 short 型,32 bit 的 long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致大端存储模式和小端存储模式。
2.2练习
2.2.1练习1
设计一个小程序来判断当前机器的字节序:
#include <stdio.h>
int main()
{
int n = 1;
if(*(char*) & n == 1)printf("小端\n");
elseprintf("大端\n");
//0x00 00 00 01
//01 00 00 00
//00 00 00 01
return 0;
}
对于if语句阔号内的解析:(把下面的A换成n即可)

运行结果如下图:

2.2.2练习2
signed char a;//有符号的;char —— 1个字节 —— 8bit位。
unsigned char b;//无符号的; 2^8 —— 256。
如果是signed char 类型,那么内存中的最高位就被当做符号位。
signed char类型的取值范围是-128~127;对于unsigned char的取值范围是 0 ~ 255。

代码2:
#include <stdio.h>
int main()
{
//char到底是有符号的char还是无符号的char是取决于编译器的!
//在VS上char == signed char
char a = -1;
//10000﹍﹍0001
//11111﹍﹍1110
//11111﹍﹍1111
//11111111 —— a
signed char b = -1;//整型提升
//11111111 —— b
unsigned char c = -1;
//11111111 —— c
printf("a = %d,b = %d,c = %d",a,b,c);
//-1 -1 255
return 0;
}
运行结果如下图:

2.2.3练习3
代码3:
#include <stdio.h>
int main()
{
char a = -128;//1000﹍﹍10000000 —> 1111﹍﹍01111111
printf("%u\n",a);//?4294967168//—> 1111﹍﹍10000000
//%u的形式打印,是认为a中存放的是无符号数//10000000 —— a//整型提升
//a是char类型,首先要整型提升
return 0;
}
运行结果如下图:

代码4:
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);//4294967168
return 0;
}
运行结果如下图:

2.2.4练习4
代码5:
//signed short -32768 ~ 32767
//unsigned char 0 ~ 65535
#include <stdio.h>
int main()
{
char a[1000];//0 ~ 999
int i;
for(i = 0;i < 1000;i++)
{
a[i] = -1-i;
}
//-1 -2 -3 -4 ﹍﹍ -127 -128 127 126 ﹍﹍ 4 3 2 1 0 -1 -2 ﹍﹍
printf("%zd",strlen(a));//求的是字符串的长度,统计的是\0(ASCII码值是0)之前的字符个数
//255
return 0;
}
运行结果如下图:


2.2.5练习5
代码6:
#include <stdio.h>
unsigned char i = 0;//unsigned char 的取值范围是0 ~ 255
int main()
{
for(i = 0;i <= 255;i++)
{
printf("hello world\n");//死循环打印
}
return 0;
}
运行结果如下图:


代码7:
#include <stdio.h>
int main()
{
unsigned int i;
for(i = 9;i >= 0;i--)//死循环
{
printf("%u\n",i);
}
return 0;
}
运行结果如下图:


2.2.6练习6
代码8:
#include <stdio.h>
//X86环境小端字节序
int main()
{
int a[4] = {1,2,3,4};//1.指针+1,取决于指针的类型;2.整数+1,就是+1。//&a —— int(*)[4]
int*ptr1 = (int*)(&a + 1);
int*ptr2 = (int*)((int)a + 1);
printf("%x,%x",ptr1[-1],*ptr2);//4 2000000
return 0;
}

三、浮点数在内存中的存储
浮点数:float、double、long double类型
浮点数表示的范围:float.h中定义;整数的取值范围:limits.h中定义。
3.1练习
练习代码如下:求其运行结果
#include <stdio.h>
int main()
{//说明:整数和浮点数在内存中的存储方式是不一样的。
int n = 9;
float*pFloat = (float*)&n;//int*
printf("n的值为: %d\n",n);//9
printf("*pFloat的值为: %f\n",*pFloat);//0.000000
*pFloat = 9.0;
printf("n的值为: %d\n",n);//1091567616
printf("*pFloat的值为:%f\n",*pFloat);//9.000000
return 0;
}
运行结果如下图:

3.2浮点数的存储
根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:
V = (-1)S * M * 2E
(-1)S表示符号位,当S = 0,V为正数;当S = 1,V为负数。
M表示有效数字,M是大于等于1,小于2的。
2E表示指数位
如下图所示:

注:所以浮点数的存储,其实存储的就是S,M,E相关的值。
IEEE 754规定:
对于32位的浮点数(float),最高的1位存储符号位S,接着的8位存储指数E,剩下的32位存储有效数字M。
对于64位的浮点数(double),最高的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M。
3.2.1 浮点数存的过程
IEEE 754对有效数字M和指数E,还有一些特别规定:
1 <= M <2,M可写为1.xxxxxx的形式,其中xxxxxx表示小数部分。
IEEE754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分,比如:保存1.01时,只保存01,等读取时,再把第一位的1加上,这样做的目的是节省1位有效数字。
至于指数E,情况比较复杂:
首先,E为一个无符号整数(unsigned int) E为8位,0 ~ 255;E为11位,0 ~ 2047。
我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023.比如,2^10的E是10,所以保存32位浮点数时,必须保存成10+127=137,即10001001。即使是浮点数也是有最大值和最小值。
E也是有最大值和最小值的, E+127 E+1023
int main()
{//5.5
float f = 5.5f;
//5.5 —> 101.1 —> 1.011*2^2 —> (-1)^0*1.011*2^2
//S = 0 M = 1.011 E = 2
//2 + 127 = 129
//01 00 0000 1011 00000000000000000000
//40 B0 00 00
return 0;
}
3.2.2 浮点数取的过程
指数E从内存中取出还可以分成三种情况:
E不全为0或者不全为1
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或者1023),得到真实值,再将有效数字M前加上第1位的1。
E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0,xxxxxx的小数,这样做是为了表示±0,以及接近于0的很小的数字。
E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号S)
3.3题目解析
代码如下:
#include <stdio.h>
int main()
{
int n = 9;
float*pFloat = (float*)&n;//int*
printf("n的值为: %d\n",n);//9
printf("*pFloat的值为: %f\n",*pFloat);//0.000000
//站在pFloat的视角,它会认为自己指向的是1个float类型的数值,当内存中的E为全0的时候,真实的E:1-127 —> -126 有效数字M,取出后不再加上第1位的1
//(-1)^0*0.0000﹍01001*2^(-126) ≈ 0
*pFloat = 9.0;
printf("n的值为: %d\n",n);//1091567616
printf("*pFloat的值为: %f\n",*pFloat);//9.000000
return 0;
}
图文解释:

四、总结
本文详细讨论了整数和浮点数在内存中的存储方式以及相关的字节序和浮点数表示方法。文章主要涉及了三部分内容:整数在内存中的存储,大小端字节序的判断与实现,以及浮点数在内存中的存储和转换。
4.1整数在内存中的存储
文章首先介绍了整数在内存中的存储方式。整数使用原码、反码和补码三种形式表示,其中,原码是最直接的表示方式,反码是通过对原码符号位之外的所有位取反得到的,而补码则是在反码的基础上加1得到。补码在计算机中被广泛应用,因为它不仅能有效表示正负数,还简化了加法和减法操作。计算机中所有整数的存储都是以补码的形式进行的,这样可以统一处理符号位和数值域,并且不需要额外的硬件支持,这使得计算更加高效。
4.2大小端字节序
文章进一步探讨了大小端字节序的问题。在计算机系统中,超过一个字节的数据如何存储在内存中,会受到字节序的影响。字节序分为大端和小端两种模式。在大端字节序中,数据的高位字节存储在低地址处,低位字节存储在高地址处;而在小端字节序中,低位字节存储在低地址处,高位字节存储在高地址处。这种存储顺序的差异,主要是由于计算机处理器的寄存器宽度大于一个字节,导致了如何安排多字节数据的问题。文章还通过代码示例,展示了如何判断当前系统的字节序。通过访问内存中的字节,判断数据的存储顺序,从而确定系统使用的是大端还是小端字节序。
4.3浮点数在内存中的存储
接着,文章讲解了浮点数在内存中的存储方式。浮点数采用IEEE 754标准来表示,在此标准下,浮点数由符号位、指数部分和有效数字部分组成。对于32位的浮点数(float类型),符号位占1位,指数占8位,有效数字占23位。对于64位的浮点数(double类型),符号位占1位,指数占11位,有效数字占52位。浮点数的表示使用科学计数法,其中符号位表示正负,指数部分表示数字的范围,有效数字则表示具体的数值。通过这种表示方法,浮点数能够有效表示非常大或非常小的数值,且能够处理精确的小数部分。
浮点数的存储与整数有所不同,尤其是在对存储内容的解读时,浮点数的指数和有效数字需要特殊处理。例如,当浮点数的指数部分全为0时,它表示的是接近于0的非常小的数字,而不是普通的0。对于有效数字部分,IEEE 754标准规定了它的存储方式,即默认保留第一位为1,因此只存储后续的小数部分。这些存储规则有助于节省内存空间,同时确保浮点数的精度和范围。
4.4总结
通过本篇文章,我们了解了整数和浮点数在内存中的存储原理,以及大小端字节序的差异。对于整数,补码的存储方式提供了一个简洁高效的处理方案,能够统一处理符号和数值域。大小端字节序的存在是由于处理器寄存器的宽度大于一个字节,在不同的系统中会有不同的存储顺序。浮点数的存储则遵循IEEE 754标准,通过符号位、指数和有效数字来表示浮动的数值范围。所有这些知识对于理解计算机内部的数据存储和处理方式至关重要,尤其是当我们需要优化程序或进行低级编程时。
相关文章:
【C语言系列】数据在内存中存储
数据在内存中存储 一、整数在内存中的存储二、大小端字节序和字节序判断2.1什么是大小端?2.2练习2.2.1练习12.2.2练习22.2.3练习32.2.4练习42.2.5练习52.2.6练习6 三、浮点数在内存中的存储3.1练习3.2浮点数的存储3.2.1 浮点数存的过程3.2.2 浮点数取的过程 3.3题目…...
【中文翻译】第12章-The Algorithmic Foundations of Differential Privacy
由于GitHub项目仅翻译到前5章,我们从第6章开始通过大语言模型翻译,并导出markdown格式。 大模型难免存在错漏,请读者指正。 教材原文地址:https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 12 其他模型 到目前为止&…...
图解模糊推理过程(超详细步骤)
我们前面已经讨论了三角形、梯形、高斯型、S型、Z型、Π型6种隶属函数,下一步进入模糊推理阶段。 有关六种隶属函数的特点在“Pi型隶属函数(Π-shaped Membership Function)的详细介绍及python示例”都有详细讲解:https://lzm07.b…...
datawhale组队学习-大语言模型-task5:主流模型架构及新型架构
目录 5.3 主流架构 5.3.1 编码器-解码器架构 5.3.2 因果解码器架构 5.3.3 前缀解码器架构 5.4 长上下文模型 5.4.1 扩展位置编码 5.4.2 调整上下文窗口 5.4.3 长文本数据 5.5 新型模型架构 5.5.1 参数化状态空间模型 5.5.2 状态空间模型变种 5.3 主流架构 在预训…...
为什么后端路由需要携带 /api 作为前缀?前端如何设置基础路径 /api?
一、为什么后端路由需要携带 /api 作为前缀? 1. 区分 API 端点与其他路由 在 Web 应用程序中,后端不仅需要处理 API 请求,还可能需要处理静态资源(如 HTML、CSS、JS 文件)或其他服务(如 WebSocket&#x…...
C++ 关系运算符重载和算术运算符重载的例子,运算符重载必须以operator开头
在C中,运算符重载允许为用户定义的类型(类或结构体)赋予某些内置运算符的功能。下面是一个关于关系运算符重载()和算术运算符重载()的简单例子。 示例:复数类的运算符重载 将创建一…...
建造者模式 (Builder Pattern)
建造者模式 (Builder Pattern) 是一种创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 一、基础 1.1 意图 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 1.2 适用场景 当创建复杂对象的算法应该…...
MCU vs SoC
MCU(Microcontroller Unit,单片机)和SoC(System on Chip,片上系统)是两种不同的芯片类型,尽管它们都实现了高度集成,但在设计目标、功能复杂性和应用场景上存在显著差异。以下是两者…...
RAG 架构地基工程-Retrieval 模块的系统设计分享
目录 一、知识注入的关键前奏——RAG 系统中的检索综述 (一)模块定位:连接语言模型与知识世界的桥梁 (二)核心任务:四大关键问题的协调解法 (三)系统特征:性能、精度…...
(C语言)习题练习 sizeof 和 strlen
sizeof 上习题,不知道大家发现与上一张的习题在哪里不一样嘛? int main() {char arr[] "abcdef";printf("%zd\n", sizeof(arr));printf("%zd\n", sizeof(arr 0));printf("%zd\n", sizeof(*arr));printf(&…...
Unity Animation的其中一种运用方式
Animation是Unity的旧的动画系统,先说目的,其使用是为了在UI中播放动效,并且在动效播放结束后接自定义事件而设计的 设计的关键点在于,这个脚本不是通过Animation直接播放动画片段,而是通过修改AnimationState的nor…...
湖北楚大夫
品牌出海已成为众多企业拓展业务、提升竞争力的关键战略。楚大夫(chudafu.com)作为一家专注于品牌出海、海外网络营销推广以及外贸独立站搭建的公司,凭借其专业、高效、创新的服务模式,致力于成为中国企业走向国际市场的坚实后盾与得力伙伴。楚大夫通过综…...
框架的CVE漏洞利用 php类 java类 手工操作和自动化操作蓝队分析漏洞利用的流量特征
前言 php重要框架和基本的识别特征 php的主要是 tp框架 和 laravel 当然还有 yii等 tp的主要特征 1\报错信息: 2、图标 3、请求头 Laravel特征 1、报错信息 2、请求头 php框架CVE利用 lavarvel 工具 https://github.com/zhzyker/CVE-2021-3129 https://git…...
前端Wind CSS面试题及参考答案
目录 标准盒模型与 IE 盒模型的区别是什么?如何通过 box-sizing 属性切换这两种盒模型? 如何计算一个元素在标准盒模型下的总宽度(包含 margin、padding、border)? 父元素高度塌陷的原因是什么?请列举至少 3 种清除浮动的方法。 方法一:使用 clear 属性 方法二:使用…...
数据结构 -- 线索二叉树
线索二叉树 线索二叉树的概念 线索二叉树的作用 我们在进行中序遍历时,总是从根节点出发进行二叉树遍历,而当仅知道某一孩子节点的指针时,由于无法访问父节点,所以没有办法进行遍历。由此引入线索二叉树 【思考】①如何找到指定…...
【算法day19】括号生成——数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
括号生成 https://leetcode.cn/problems/generate-parentheses/description/ 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 左括号数必须大于右括号数,且小于等于n class Solution { publ…...
Qt5.15.2实现Qt for WebAssembly与示例
目录 1.什么是Qt for WebAssembly? 1.1 什么是 WebAssembly? 1.2 WebAssembly 的优势 1.3 什么是 Qt for WebAssembly? 1.4 Qt for WebAssembly 的特点 1.5 编译过程 1.6 运行时环境 注意!!!注意&am…...
好吧好吧,看一下达梦的模式与用户的关系
单凭个人感觉,模式在达梦中属于逻辑对象合集,回头再看资料 应该是一个用户可以对应多个模式 问题来了,模式的ID和用户的ID一样吗? 不一样 SELECT USER_ID,USERNAME FROM DBA_USERS WHERE USERNAMETEST1; SELECT ID AS SCHID, NA…...
HOW - DP 动态规划系列(三)(含01背包问题)
目录 一、01背包问题最直接的暴力解法动态规划解法 二、完全背包 通过几个算法的学习,理解和掌握动态规划来解决背包问题。 一、01背包问题 对于面试的话,掌握01背包和完全背包就够用了,最多可以再来一个多重背包。 如果这几种背包分不清&…...
Linux的文件上传下载的lrzsz库的安装与使用
以下是关于 Linux 下 lrzsz 库的安装与使用 的详细指南,适用于通过终端(如 SecureCRT、Xshell、MobaXterm 等)使用 ZMODEM 协议快速上传和下载文件: 一、lrzsz 简介 功能:提供 rz(接收文件)和 …...
在linux服务器部署Heygem
前言: Heygem官方文档上提供了基于windwos系统的安装方案。在实际使用过程中个人电脑的配置可能不够。这个时候如果服务器配置够的话,可以尝试在服务器上装一下。但是服务器一般都是linux系统的,于是这篇教程就出现了… 可行性分析 通读安装…...
图书管理系统系统-Java、SpringBoot、Vue和MySQL开发的图书馆管理系统
「springboot、vue图书馆管理系统.zip」 链接:https://pan.quark.cn/s/5a929a7e9450 分享一个图书管理系统,Java、SpringBoot、Vue和MySQL开发的图书馆管理系统 以下是对文本内容的总结: 项目概述 项目名称与背景: 项目概述 项…...
学生管理系统(需求文档)
需求: 采取控制台的方式去书写学生管理系统 分析: 初始菜单: “----------欢迎来到java学生管理系统----------” “1:添加学生” “2:删除学生” “3:修改学生” “4:查询学生” “5:…...
[c语言日寄]数据输入
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
CMake-环境变量介绍
文章目录 作用域获取环境变量初始化查看特殊的环境变量 环境变量类似普通变量,但也有些不同,如下: 作用域 在一个CMake进程中环境变量具有全局作用域 获取环境变量 使用ENV操作符获取环境变量,例如$ENV{<name>}ÿ…...
数据预处理流程与关键步骤解析
数据预处理流程图(Markdown格式): #mermaid-svg-b3mhJcpFWaJ9qMZ8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-b3mhJcpFWaJ9qMZ8 .error-icon{fill:#552222;}#mermaid-svg-b3m…...
字节DAPO算法:改进DeepSeek的GRPO算法-解锁大规模LLM强化学习的新篇章(代码实现)
DAPO算法:解锁大规模LLM强化学习的新篇章 近年来,大规模语言模型(LLM)在推理任务上的表现令人瞩目,尤其是在数学竞赛(如AIME)和编程任务中,强化学习(RL)成为…...
计算机操作系统(四) 操作系统的结构与系统调用
计算机操作系统(四) 操作系统的结构与系统调用 前言一、操作系统的结构1.1 简单结构1.2 模块化结构1.3 分层化结构1.4 微内核结构1.5 外核结构 二、系统调用1.1 系统调用的基本概念1.2 系统调用的类型 总结(核心概念速记)…...
Docker安装,并pullMySQL和redis
卸载原Docker 您的 Linux 发行版可能提供非官方的 Docker 软件包,这可能与 Docker 提供的官方软件包冲突。在安装 Docker Engine 正式版之前,您必须先卸载这些软件包。 sudo dnf remove docker \ docker-client \ docker-client-latest \ docker-common…...
第三天 开始Unity Shader的学习之旅之第二天的补充
Unity Shader的学习笔记 第三天 开始Unity Shader的学习之旅之第二天的补充 文章目录 Unity Shader的学习笔记前言一、Unity 提供的内置文件和变量1. 内置的包含文件2. UnityCG.cginc中的常用结构体 二、Unity 提供的Cg/HLSL语义1. 从应用阶段传递模型数据给顶点着色器时Unity…...
