深入C语言内存:数据在内存中的存储

一、数据类型

1. unsigned:无符号数类型

当一个数是无符号类型时,那么其最高位的1或0,和其它位一样,用来表示该数的大小。

2.signed:有符号数类型

当一个数是有符号类型时,最高数称为“符号位”。符号位为1时,表示该数为负数,为0时表示为正数。

注意:有符号类型可以表示正数,负数或0,无符号类型仅能表示大于等于0的值

1.1 整型

有符号字符型:(signed) char// 1字节
无符号字符型:unsigned char// 1字节
有符号短整型:(signed) short// 2字节
无符号短整型:unsigned short// 2字节
有符号整型:(signed) int// 4字节
无符号整型:unsigned int// 4字节
有符号长整型:(signed) long// 4字节
无符号长整型:unsigned long// 4字节
有符号更长整型:(signed) long long// 8字节
无符号更长整型:unsigned long long// 8字节

1.2 浮点型

单精度浮点型:float //4字节
双精度浮点型:double //8字节 

1.3 构造类型

数组类型
结构体类型:struct
枚举类型:enum
联合类型:union

1.4 指针类型

//32位环境下指针变量大小 4
//64位环境下指针变量大小 8
字符指针:char*
短整型指针:short*
整型指针:int*
长整型指针:long*
更长类型指针:long long*
单精度浮点数指针:float*
双精度浮点数指针:double*
空类型指针:void*

1.5 空类型

void
//void代表无类型,常用在程序编写中对定义函数的参数类型、返回值、函数中指针类型进行声明。

二、整型的存储

2.1 原码,补码,反码

我们知道计算机存储数据是以二进制的方式,那具体是以怎样的方式存储呢

对于一个数,计算机要使用一定的编码方式进行存储,原码、反码、补码是机器存储一个具体数字的编码方式。

三种方式均有符号位数值位两部分,符号位都是0表示“正数”,1表示“负数”,而数值位分正负数而定。

正数的原码、反码、补码都相同,负数的原码、反码、补码各不相同

2.1.1 原码

直接将数值按照正负数的形式翻译成二进制就可以得到原码

+5的原码:00000000 00000000 00000000 00000101
-5的原码:10000000 00000000 00000000 00000101

2.1.2 补码

将原码的符号位不变,其他位次按位取反
即:0变为1,1变为0

+5的反码:00000000 00000000 00000000 00000101
-5 的反码:11111111 11111111 11111111 11111010

2.1.3 反码

反码符号位不变,数值为+1

+5的补码:00000000 00000000 00000000 00000110
-5的补码:11111111 11111111 11111111 11111011

反码回到原码的两种方式:

1、补码-1后 取反得到原码
2、补码取反后 +1得到原码

计算机内存数值的存储方式是补码!

2.2 大小端

2.2.1 什么是大小端

大端存储模式:指数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中

小端存储模式:指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中

具体是什么意思呢~

首先我们得知道内存中数据是以16进制表示的

int a=0x11223344//十六进制
小端存储44332211

                                                                低地址                                           高地址

大端存储11223344

                                                                低地址                                           高地址

2.2.2 怎么判断大小端

我们可以通过取出第一位,也就是低地址的数来进行判断。

那我们如何取出第一位呢~,这就需要我们对指针的灵活运用了

我们知道第一位相当于一个字节,而char类型就是一个字节,所以用(char*)进行强制类型转换并取出就行了

#include<stdio.h>
int main()
{int a = 1;char* p = (char*) & a;//强制类型转换if (*p == 1)printf("小端");elseprintf("大端");return 0;
}

三、整型截断

整型截断是将所占字节大的元素赋给所占字节小的元素时会出现数值的舍去现象。

简单来说就是将长字节内容截取一部分赋给短字节内容

 char i = -1;//-1是整型4个字节,char类型1个字节,发生整型截断
  1. 原码:1000000 0000000 0000000 0000001
  2. 反码:11111111 11111111 11111111 11111110
  3. 补码:11111111 11111111 11111111 11111111

     char类型有八个比特位,截取后八位

  1. i的补码:11111111
  2. i的反码:11111110
  3. i的原码:1000001

 所以i仍是-1

四、整型提升

C的整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。为了获得这个精度,表达式中的字符短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。

有符号的整型提升高位补符号位,无符号的整型提升高位补0

4.1 正整数的整型提升

 char a=1;//补码:00000001//有符号,符号位是0,提升为00000000000000000000000000000001

4.2 负数的整型提升

  char b=-1;//补码:1111111//有符号,符号位是1,提升为11111111111111111111111111111111

4.3 无符号数的整型提升

  unsigned c=-1//补码:1111111//无符号,补0,提升为00000000000000000000000011111111

五、浮点型在内存中的存储

5.1 浮点型运算规则

要表示浮点数的第一步,就是让小数也能使用二进制来表示。我们知道二进制表示整数时,最低位代表2的0次方,往高位依次是2的1次方,2次方,3次方……那么对应的,二进制数小数点后面,最高位则是2的-1次方,-2次方,-3次方……

根据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

(-1) ^ S * M * 2 ^ E

1.  (-1) ^ S 表示符号位,当S=0时,V为正数;当S=1时,V为负数
2.  M 表示有效数字,且1 <= M <2
3.  2 ^ E表示指数位

⼗进制的5.0,写成⼆进制是 101.0 ,相当于 1.01×2^2 。

那么,按照上⾯V的格式,可以得出S=0,M=1.01,E=2。

对于32位的浮点数float,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M

对于64位的浮点数double,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

5.2 浮点数取得过程

5.2.1 对于M的规定

1 ≤ M < 2 ,即M可以写成1.xxxxxx的形式。IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

5.2.2 对于E的规定

1. E不全为0或不全为1

这时,浮点数就采⽤下⾯的规则表⽰,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第⼀位的1。

如一个浮点数存储方式如下:

0 01111110 00000000000000000000000

  1. 首先将 01111110 转换为十进制为126
  2. 再将126-127=-1,所以指数位为-1
  3. 有效数字部分为0,所以表示1.0
  4. 符号位0,是个正数,所以表示的浮点数是1.0*2^-1=0.5
2. E全为0

这时候指数为0-127,最后肯定得到一个很小的数,所以特别规定

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。

3. E全为1

255 - 127 = 128 或 2047 - 1023 = 1024, 与第二点相反,这时这个数可能无穷大,所以也特别规定

这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/302245.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s知识

k8s是用于容器编排和管理的&#xff0c;docker或者ctr是k8s的运行时&#xff0c;k8s通过容器运行时来启动容器&#xff0c;容器启动需要镜像&#xff0c;镜像可以用docker构建&#xff0c;dockerfile就是用于自定义如何构建镜像&#xff0c;所以上面那套流水线就是先用dockerfi…

【Linux】TCP编程{socket/listen/accept/telnet/connect/send}

文章目录 1.TCP接口1.1socket文档 1.2listen拓&#xff1a;端口号8080 1.3accept拓&#xff1a;今天全局函数 1.4读写接口1.5telnet1.一个客户端2.两个客户端 1.6ulimit -a1.7常识回顾1.8connect1.9拓&#xff1a;客户端的ip和地址什么时候被分配&#xff1f;1.10拓&#xff1a…

Linux应用开发(3):Linux时间操作(time、mktime、localtime等)

1. 简述 在Linux系统中&#xff0c;时间操作函数是编程中经常使用的一部分&#xff0c;它们允许程序获取和设置系统时间&#xff0c;以及对时间进行各种处理。以下是一些常用的时间操作函数的详细介绍。 2. 时间操作 &#xff08;1&#xff09;time(): 获取1970年1月1日以来的…

18 Games101 - 笔记 - 高级光线传播与复杂外观建模

**18 ** 高级光线传播与复杂外观建模 本章虽然是高级光线传播与复杂外观建模&#xff0c;但是都没有展开讲&#xff0c;不涉及具体的计算。 高级光线传播 无偏的光线传播&#xff1a;如果无论样本多少&#xff0c;算出来的期望值永远是对的。例如蒙特卡洛积分&#xff0c;它…

vue3中使用webstocket

1.在项目中创建webstocket.ts文件 export default class SocketService {// 单例static instance null;static get Instance() {if (!this.instance) {this.instance new SocketService();}return this.instance;}// 和服务端连接的socket对象ws null;// 存储回调函数callB…

nestjs 全栈进阶--nest生命周期

视频教程 12_nestjs生命周期_哔哩哔哩_bilibili 所有应用程序元素都有一个由 Nest 管理的生命周期。Nest 提供了生命周期钩子&#xff0c;提供了对关键生命时刻的可见性&#xff0c;以及在关键时刻发生时采取行动(在你的module&#xff0c;injectable或者controller中注册代码…

ddres( ) 组站星双差方程和设计矩阵

1 ddres( )参数介绍 rtklib中进行的单频解算 双差观测值&#xff0c;单差的模糊度 单频点双差 DD (double-differenced) phase/code residuals ------------------------------ x 模糊度 P 方差-协方差阵 sat 共识卫星列表 ns 共识卫星数量 y…

Qt | Q_PROPERTY属性和QVariant 类

一、属性基础 1、属性与数据成员相似,但是属性可使用 Qt 元对象系统的功能。他们的主要差别在于存取方式不相同,比如属性值通常使用读取函数(即函数名通常以 get 开始的函数)和设置函数(即函数名通常以 set 开始的函数)来存取其值,除此种方法外,Qt 还有其他方式存取属性值…

DFS:深搜+回溯+剪枝解决排列、子集问题

创作不易&#xff0c;感谢三连支持&#xff01;&#xff01; 一、全排列I . - 力扣&#xff08;LeetCode&#xff09; class Solution { public://全局变量vector<vector<int>> ret;vector<int> path;bool check[6];vector<vector<int>> perm…

DDD 的四层领域模型是怎样的?包含哪些基础概念?

DDD的四层领域模型如下所示&#xff1a; 展现层&#xff1a;这一层负责向用户显示信息和解释用户命令&#xff0c;完成前端界面逻辑。并将用户请求传递给应用层。应用层&#xff1a;这一层是很薄的一层&#xff0c;负责协调领域层中的领域对象&#xff0c;组成具体应用场景。应…

深度解析Elasticsearch索引数据量过大的优化与部署策略

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 一. 分片和副本策略 1.1分片策略 1.1.1 数据量 1.1…

springCloudAlibaba集成gateWay实战(详解)

一、初识网关&#xff1f; 1、网关介绍 ​ 在微服务架构中&#xff0c;一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢&#xff1f;如果没有网关的存在&#xff0c;我们只能在客户端记录每个微服务的地址&#xff0c;然后分别去调用。这样的话…

python爬虫———urllibd的基本操作(第十二天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

画图理解JVM相关内容

文章目录 1. JVM视角下&#xff0c;内存划分2. 类内存分布硬核详解1. 获取堆内存参数2. 扫描堆内存&#xff0c;定位实例3. 查看实例所在地址的数据4. 找到实例所指向的类信息的地址5. 查看class信息6. 结论 3. Java的对象创建流程4. 垃圾判别算法4.1 引用计数法4.2 可达性分析…

【Redis】NoSQL之Redis的配置和优化

关系型数据库与非关系型数据库 关系型数据库 关系型数据库是一个结构化的数据库&#xff0c;创建在关系型模型&#xff08;二维表&#xff09;的基础上&#xff1b;一般面向于记录&#xff1b; SQL语句(标准数据查询语句)就是一种基于关系型数据库的语言&#xff0c;用于执行…

Mysql底层原理五:如何设计、用好索引

1.索引的代价 空间上的代价 时间上的代价 每次对表中的数据进⾏增、删、改操作时&#xff0c;都需要去修改各个B树索引。⽽且我们讲过&#xff0c;B树每层节点都是按照索引列的值从⼩到⼤的顺序排序⽽组成了双 向链表。不论是叶⼦节点中的记录&#xff0c;还是内节点中的记录&a…

设计模式 -- 发布订阅模式

发布订阅模式&#xff1a; 订阅者把自己想订阅的事件注册到调度中心&#xff0c;当发布者发布该事件到调度中心&#xff0c;也就是该事件触发时&#xff0c;由调度者统一调度订阅者注册到调度中心的处理代码。 在javaScript 中我们一般使用事件模型来代替传统的发布订阅模式。 …

深入了解iOS内存(WWDC 2018)笔记-内存诊断

主要记录下用于分析iOS/macOS 内存问题的笔记。 主要分析命令&#xff1a; vmmap, leaks, malloc_history 一&#xff1a;前言 有 3 种思考方式 你想看到对象的创建吗&#xff1f;你想要查看内存中引用对象或地址的内容吗&#xff1f;或者你只是想看看 一个实例有多大&#…

互联网大厂ssp面经之路:计算机网络part2

什么是 HTTP 和 HTTPS&#xff1f;它们之间有什么区别&#xff1f; a. HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;安全超文本传输协议&#xff09;是用于在Web上传输数据的协议。它们之间的区别在于安全性和数据传输方式。 b. HTTP是一种不安全的协议&…

【随笔】Git 高级篇 -- 整理提交记录(上)cherry-pick(十五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…