【C进阶】深度剖析数据在内存中的存储
目录
一、数据类型的介绍
1.类型的意义:
2.类型的基本分类
二、整形在内存中的存储
1.原码 反码 补码
2.大小端介绍
3.练习
三、浮点型在内存中的存储
1.一个例子
2.浮点数存储规则
一、数据类型的介绍
前面我们已经学习了基本的内置类型以及他们所占存储空间的大小:
char //字符数据类型
short //短整型
int //整形
long //长整形
long long //更长的整形
float //单精度浮点型
double //双精度浮点型
1.类型的意义:
1.使用这个类型开辟内存空间的大小(大小决定了使用的范围)
2.决定了如何看待内存空间的视角:
int 和float类型都是4个字节,但是一个是整形,一个是浮点型,看待内存空间的视角不一样
2.类型的基本分类
(1)整形家族:
char:
unsigned char
signed char
short :
unsigned short [int] //短整型,这个int整形可以省略
signed short [int]
int :
unsigned int
signed int
long :
unsigned long [int]
signed long [int]
【温馨提示】:char类型也是整形家族的原因:
字符在内存中存储的是字符的ACSII码值(0-127),ASCII码值是整形,所以字符类型归类到整形家)族
signed -有符号的:当第一位代表符号位的时候,就是有符号的
unsigned -无符号的:当每一位都是数值位,有效位的时候就是无符号的
【注意】:
当我们没有写signed和unsigned时,int,short和long类型默认就是signed有符号的
eg:当我们写出int a的默认的其实就是signed int类型
but :C语言并没有规定char是否是signed char(这个取决于编译器,大部分是signed char)
(2)浮点数家族:都可以表示小数
float //精度小一些,单精度
double //精度大一些,双精度
(3)构造类型(自定义类型)
>数组类型
>结构体类型 struct
>枚举类型 enum
>联合类型 union
(4)指针类型
int *pi
char *pc
float *pf
void * pv (无具体类型的指针)
(5) 空类型
void 表示空类型(无类型)
通常应用于函数的返回类型,函数的参数,指针类型
eg:int main(void)就表示main函数不需要参数
但是实际上main函数是有三个参数的int main(int argc,char *argv[ ],char *envp[ ]),这三个参数需要用的时候才需要写,不需要括号直接写void即可
二、整形在内存中的存储
计算机能够处理的是二进制数据,整形和浮点型在内存中也都是以二进制的形式进行存储的
1.原码 反码 补码
整形的二进制表示有三种:原码,反码,补码
正的整数:原码,反码,补码相同
负的整数:原码,反码,补码要进行计算
整数在内存中存储的是补码的二进制序列
eg:
int a = -10;//int类型占4个字节-32bit位
10000000 00000000 00000000 00001010 原码
11111111 11111111 11111111 11110101 反码
1 1111111 11111111 11111111 11110110 补码(最高一位表示符号位,其他31位表示数值位)unsigned int b = -10;
1 1111111 11111111 11111111 11110110 补码(32位全都表示数值位)
对于整形来说,数据存放内存中其实存放的是补码
为什么呢?
使用补码,可以将符号位和数值域统一处理;同时,加减法也可以统一处理(cpu只有加法器),此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路
eg:
1-1
电脑转化为1+(-1)
00000000 00000000 00000000 00000001 1的原反补码
10000000 00000000 00000000 00000001 -1的原码
11111111 11111111 11111111 11111110 -1的补码
11111111 11111111 11111111 11111111 -1的补码
如果就是简单的原码相加得到的就是-2(还会犹豫要不要加符号位)
但是如果是补码相加得到的就是正确的结果,每个位上不断进1,最后最前面多出来一位为1直接舍弃,其他位都为0
2.大小端介绍
int a=0x11223344(根据数据的存储44位于低字节处,11位于高字节处)
大端字节序存储:
把一个数据的低位字节处的数据存放在内存的高地址处,高位字节处的数据存放在内存的低地址处
小端字节序存储:
把一个数据的低位字节处的数据存放在内存的低地址处,高位字节处的数据存放在内存的高地址处
【注意】:数据存放的时候是以字节为单位存储讨论顺序的,所以叫做大小端字节序存储
char类型不需要考虑大小端,char类型就占一个字节,没有顺序可言
为什么存在大小端字节序存储呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式
百度笔试题:
请简述大端字节序和小端字节序的概念,设计一个程序来判断当前机器的字节序
思路:
给一个int类型的变量a:让其为1(这样十六进制简单0x 00 00 00 01),然后再通过char*一次访问一个字节,打印出来看是00还是01,从而判断大小端
代码实现:
#include<stdio.h>
int main()
{int a = 1;char* p = (char*)&a; //要将&a(int *)强制转化为char *if (*p == 1)printf("小端\n");elseprintf("大端\n");return 0;
}
【自定义函数进行判断】:
#include<stdio.h>
int check_sys()
{int a = 1;return *(char*)&a;
}
int main()
{if(check_sys()==1)printf("小端\n");elseprintf("大端\n");return 0;
}
3.练习
<1>下面程序输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;printf("a=%d,b=%d,c=%d",a,b,c);return 0;
}
答案:
-1 -1 255
解释:
首先-1是整数,原码:10000000 00000000 00000000 00000001
反码:111111111 111111111 111111111 111111110
补码:111111111 111111111 111111111 111111111
但是char类型只有8个比特位,所以补码存起来就是111111111,而且第一位为符号位(对于a和b)
%d是10进制的形式打印有符号的整数
那么就需要进行整形提升(无符号数高位补0,有符号数高位补符号位)(对原码整形提升)
对于a和b:整形提升后补码为111111111 111111111 111111111 111111111(也就是-1)
对于c:整形提升后补码为00000000 00000000 00000000 111111111(又因为是无符号的整形,补码和原码一样)(也就是255)
<2>下面程序输出什么?
#include <stdio.h>
int main()
{char a = -128;printf("%u\n", a);return 0;
}
答案:
4294967168
解释:
-128的原码:10000000 00000000 00000000 10000000
反码:111111111 111111111 111111111 011111111
补码:111111111 111111111 111111111 10000000
存进a的补码:10000000(1为符号位)
对a进行整形提升:111111111 111111111 111111111 10000000(有符号位高位补符号位1)
%u是10进制的形式打印无符号的整数
那么打印就当a是无符号数打印,对于无符号数原反补码相同,直接算即可
<3>下面程序输出什么?
#include <stdio.h>
int main()
{char a = 128;printf("%u\n", a);return 0;
}
答案:
4294967168
解释:
虽然signed char最大只能是127,但是还是可以赋值为128,可以自行截断
128的原码:00000000 00000000 00000000 10000000
存进a的补码:10000000(1为符号位)
对a进行整形提升:111111111 111111111 111111111 10000000(有符号位高位补符号位1)
10进制无符号形式打印
【总结】:
signed char:-128~127
char-假设是有符号的char(1个字节=8bit) (第一位为符号位)第一列为原码
00000000 0
00000001 1
00000010 2
00000011 3
... ...
011111111 127
10000000 -128 11111111(反) 110000000(补:多出来一位要删去)
10000001 -127 11111110 111111111
...
111111110 -2 10000001 10000010
111111111 -1 10000000 10000001
假设是unsigned char:0~255
00000000
00000001 1
00000010 2
00000011 3
...
011111111 127
10000000 128
...
111111110 254
111111111 255

<4>下面程序输出什么?
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
答案:
-10
解释:
-20:原码:10000000 00000000 00000000 00010100
反码:111111111 111111111 111111111 11101011
补码:111111111 111111111 111111111 11101100
10:原反补码:00000000 00000000 00000000 00001010(相加时最高位变为符号位)
补码进行相加:111111111 111111111 111111111 11110110(补码)
反码:10000000 00000000 00000000 00001001
原码:10000000 00000000 00000000 00001010(-10)
<5>下面程序输出什么?
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
答案:
9到0再到4294967295,一直减小,死循环
解释:
unsigned int的范围就是>=0的,所以for循环的判断条件恒成立,类比unsigned char当0继续减小,就到了255,unsigned int也是这样的
<6>下面程序输出什么?
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
答案:
255
解释:
strlen是统计\0(也就是0)之前的字符个数
a[ i ]里面放的是-1,-2,-3...-128 127 ...6 5 4 3 2 1 0
一共就是128+127=255个数
<7>下面程序输出什么?
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
答案:
死循环
解释:
unsigned char的范围就是0-255,for循环的条件恒成立,进入死循环
三、浮点型在内存中的存储
常见的浮点数:
3.14159
1E10(也就是1.0*10^10)
浮点数家族包括:float,double,long double类型
浮点数表示的范围:float.h中定义
1.一个例子
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
结果:

2.浮点数存储规则
任意一个二进制浮点数V可以表示成下面的形式:

eg:10进制的5.5转化为二进制
101.1(小数点后面一位就是2的-1次方也就是0.5)
二进制浮点数表示也就是(-1)^0*1.011*2^2(小数点提前两位,也就是*2^2(二进制),如果是十进制就是2^10)
得出:S=0,M=1.011,E=2
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M

对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M

有效数字M的存储:
对于有效数字M,1<=M<2,在计算机内部保存M的时候,默认小数点前面一位为1,所以保存只保存小数点后面的数字,这样就节省了一位数的空间,以32位为例,虽然留给M只有23位,但是相当于保存了24位有效数字
有效数字E的存储:
首先E是一个为无符号数,如果E为8位,它的取值范围为0-255;如果E为11位,它的取值范围为0-2047。存入E的真实值时必须加上一个中间值,对于8位的E这个中间值为127,对于11的E,这个中间值为1023
eg:2^10的E为10,所以保存32位浮点数时,必须保存成10+127=137,即10001001
指数E从内存中取出还可以再分成三种情况:
(1)E不全为0或不全为1:
指数E的计算值减去127(或1023),得到真实值,再将M小数点前面的1补上
eg:
0.5的二进制为0.1,浮点数表示:1.0*2^(-1),E存储为-1+127=126,也就是01111110,而尾数1.0去除1就是0,那么0.5的二进制表示形式就是:
0 01111110 00000000000000000000000
(2)E全为0:
这时浮点数的指数E等于1-127(或者1-1023)即为真实值
M这时也不需要加上小数点前面的1,而是还原成0.xxxx的小数,这样做是为了表示正负0,以及接近于0的很小的数
(3)E全为1:
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)
现在再来解释一下前面的例子:
从int类型的9来看:
int n=9;
00000000 00000000 00000000 00001001(int类型二进制)
但是当它强制类型转化为float*时,代表的含义就不一样了
0 00000000 00000000000000000001001
这时的E为全0,那么E=-126,M也不用补0,即M=0.00000000000000000001001,S=0
那么*pFloat也就是(-1)^0*0.00000000000000000001001*2^(-126),这个数是极其小的,打印出来就直接是0.000000(float打印小数点后6位)
从float类型的9.0来看:(当*pFloat=9.0以后)
9.0(1001.0)
浮点型表示形式:(-1)^0*1.001*2^3
二进制表示:0 10000010 00100000000000000000
然后%d形式打印:n的视角看这是补码,符号位是0,为正数,原反补码相同,转化为10进制也就是1091567616
本次内容就到此啦,欢迎评论区或者私信交流,觉得笔者写的还可以,或者自己有些许收获的,麻烦铁汁们动动小手,给俺来个一键三连,万分感谢 !

相关文章:
【C进阶】深度剖析数据在内存中的存储
目录 一、数据类型的介绍 1.类型的意义: 2.类型的基本分类 二、整形在内存中的存储 1.原码 反码 补码 2.大小端介绍 3.练习 三、浮点型在内存中的存储 1.一个例子 2.浮点数存储规则 一、数据类型的介绍 前面我们已经学习了基本的内置类型以及他们所占存储…...
TortoiseGit安装
一、安装Git环境 Git-2.42.0-64-bit.exe (访问密码: 1666)https://url48.ctfile.com/f/33868548-924037167-76e273?p1666 二、安装TortoiseGit TortoiseGit-2.14.0.1-64bit.msi (访问密码: 1666)https://url48.ctfile.com/f/33868548-924037173-d395c7?p1666 三、安装T…...
巨人互动|游戏出海游戏出海的趋势如何
随着全球游戏市场的不断扩大和消费者需求的多元化,游戏出海作为游戏行业的重要战略之一,正面临着新的发展趋势。本文小编将讲讲游戏出海的趋势,探讨一下未来游戏出海的发展方向与前景。 巨人互动|游戏出海&2023国内游戏厂商加快“出海”发…...
k8s 安装 istio(二)
3.3 部署服务网格调用链检测工具 Jaeger 部署 Jaeger 服务 kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/jaeger.yaml 创建 jaeger-vs.yaml 文件 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata…...
Postman中参数区别及使用说明
一、Params与Body 二者区别在于请求参数在http协议中位置不一样。Params 它会将参数放入url中以?区分以&拼接Body则是将请求参数放在请求体中 后端接受数据: 二、body中不同格式 2.1 multipart/form-data key - value 格式输入,主要特点是可以上…...
基于python+pyqt的opencv汽车分割系统
目录 一、实现和完整UI视频效果展示 主界面: 识别结果界面: 查看分割处理过程图片界面: 二、原理介绍: 加权灰度化 编辑 二值化 滤波降噪处理 锐化处理 边缘特征提取 图像分割 完整演示视频: 完整代码链…...
游戏设计的主要部分
游戏设计的主要部分 介绍 游戏设计是创建有趣、挑战性和令人满足的游戏体验的过程。它涵盖了许多方面,从概念开发到实际实施,以及最终的游戏测试和优化。游戏设计师需要考虑玩家的情感、技能挑战、故事情节、游戏世界等多个要素,以确保游戏…...
架构师成长之路Redis第二篇|Redis配置文件参数讲解
Redis.conf文件 官网Redis文档链接:Redis官网 官网Redis config配置文件参数讲解:https://redis.io/docs/management/config/ Redis.conf参考模板例子 : https://redis.io/docs/management/config-file/ Redis 可以使用内置的默认配置在没有配置文件的情况下启动,但是仅…...
jsp+servlet+mysql阳光网吧管理系统
项目介绍: 本系统使用jspservletmysql开发的阳光网吧管理系统,纯手工敲打,系统管理员和用户角色,功能如下: 管理员:修改个人信息、修改密码;机房类型管理;机房管理;机位…...
Next.js基础语法
Next.js 目录结构 入口App组件(_app.tsx) _app.tsx是项目的入口组件,主要作用: 可以扩展自定义的布局(Layout)引入全局的样式文件引入Redux状态管理引入主题组件等等全局监听客户端路由的切换 ts.config…...
selenium进阶之web自动化项目框架搭建(Python版)
web自动化项目框架搭建 1、项目结构 web自动化框架的设计,同接口自动化框架一样,采用分层设计。 文件或目录说明common常用模块,常用的一些函数封装testcases用例模块,所有的测试用例test_data用例数据logs日志目录reports报告s…...
qt设计界面
widget.h #ifndef WIDGET_H #define WIDGET_H //防止文件重复包含#include <QWidget> //QWidget类所在的头文件,父类头文件 #include<QIcon> #include<QPushButton> …...
《C和指针》笔记12: 存储类型(自动变量、静态变量和寄存器变量)
文章目录 1. 自动变量(auto)1.1 自动变量的初始化 2. 静态变量(static)2.1 静态变量的初始化 3. 寄存器变量(register) 1. 自动变量(auto) 在代码块内部声明的变量的缺省存储类型是…...
无限计算力:探索云计算的无限可能性
这里写目录标题 前言云计算介绍服务模型: 应用领域:云计算主要体现在生活中的地方云计算未来发展的方向 前言 云计算是一种基于互联网的计算模型,通过它可以实现资源的共享、存储、管理和处理。它已经成为许多个人、企业和组织的重要技术基础…...
【赋权算法】Python实现熵权法
在开始之前,我们先说一下信息熵的概念。 当一件事情发生,如果是意料之中,那么这个事情就并不能拿来当做茶余饭后的谈资,我们可以说这个事情并没有什么信息和价值。而当一件不可能发生的事情发生的时候,我们可能就会觉…...
docker之 Consul(注册与发现)
目录 一、什么是服务注册与发现? 二、什么是consul 三、consul 部署 3.1建立Consul服务 3.1.1查看集群状态 3.1.2通过 http api 获取集群信息 3.2registrator服务器 3.2.1安装 Gliderlabs/Registrator 3.2.2测试服务发现功能是否正常 3.2.3验证 http 和 ng…...
用NeRFMeshing精确提取NeRF网络中的3D网格
准确的 3D 场景和对象重建对于机器人、摄影测量和 AR/VR 等各种应用至关重要。 NeRF 在合成新颖视图方面取得了成功,但在准确表示底层几何方面存在不足。 推荐:用 NSDT编辑器 快速搭建可编程3D场景 我们已经看到了最新的进展,例如 NVIDIA 的…...
权限提升-Windows本地提权-AT+SC+PS命令-进程迁移-令牌窃取-getsystem+UAC
权限提升基础信息 1、具体有哪些权限需要我们了解掌握的? 后台权限,网站权限,数据库权限,接口权限,系统权限,域控权限等 2、以上常见权限获取方法简要归类说明? 后台权限:SQL注入,数…...
深入了解Kubernetes(k8s):安装、使用和Java部署指南(持续更新中)
目录 Docker 和 k8s 简介1、kubernetes 组件及其联系1.1 Node1.2 Pod1.3 Service 2、安装docker3、单节点 kubernetes 和 KubeSphere 安装3.1 安装KubeKey3.2 安装 kubernetes 和 KubeSphere3.3 验证安装结果 4、集群版 kubernetes 和 KubeSphere 安装5、kubectl 常用命令6、资…...
Oracle的学习心得和知识总结(二十九)|Oracle数据库数据库回放功能之论文三翻译及学习
目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《Oracle Database SQL Language Reference》 2、参考书籍:《PostgreSQL中文手册》 3、EDB Postgres Advanced Server User Gui…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
