鹏哥C语言复习——数据存储

目录

版本差异:

数据类型:

进制表示:

大小端储存:

数据运算:

浮点型在内存中的存储:


版本差异:

debug和release的区别:

在栈区开辟地址一般是先从高地址开辟
debug创建数组和单个变量后,变量地址放在数组后,即变量地址高于数组地址(先创建变量再创建数组)这种情况下可能会导致死循环(2photos)

Release创建数组和单个变量后,变量地址放在数组前,及变量地址低于数组地址(自动进行了代码优化)

 

以上代码在vscode中进行的

Debug通常为调试版本,包含调试信息,并且不做任何优化,便于程序员调试程序

Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用

数据类型:

数据类型详细介绍:

Char1 short2 int4 long4/8(32位平台下和64位平台下的区别)

Long long8(c99) float4 double8

 

 

Char在整型家族里,字符的本质是ASCII码值,是整型,所以划分到整型家族

Int a; ----> signed int a;

Unsigned int a; ----> unsigned int a;

Short、long、long long同

Single char 是哪一个标准未定义,是由编译器决定的

符号位是0表示正数,1表示负数

Float的精度低,存储的数据范围较小;double的精度高,存储的数据范围大

Void* 万能指针类型,在指针复习该文中讲解过

Void test(void)

//第一个void表示函数不会有返回值

//第二个void表示函数不需要传任何参数

进制表示:

假设我要表示在10进制下为21的数据

二进制:0b10101

八进制:025

十六进制:0x15

十进制:1*1+10*2 =21

整数的二进制表示有三种表示形式:

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

负的需要通过计算

原码:直接通过正负的形式写出的二进制序列就是原码

反码:原码的符号位不变,其他位按位取反

补码:反码+1就是补码

更多原码、反码与补码讲解:操作符讲解

计算机储存的是补码

原因:使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路

进制位计算:

一个16进制位是4个2进制位,因为 2 ^ 4 = 16

大小端储存:

计算机是以字节为单位存入,最后计算机只保留了两种存储形式,假设一个数据地址为0x11 22 33 44 则存入为11 22 33 44 或者44 33 22 11(都是指从低地址到高地址)

11 22 33 44:大端字节序存储,把一个数据的高位字节序的内容存放在低地址处,把低位字节序内容放在高地址处,就是大端字节序存储

44 33 22 11:小段字节序存储,与11 22 33 44 的存储方式相反

巧计:大的数值放高位(高地址)即为大端字节序存储,小的数值放高位(高地址)即为小端字节序存储

数据大小含义

例如int i = 20

i的16进制表示方式即为0x 00 00 00 14,其中14为最大字节序,即使该处代表的是16^0和16^1,但是0永远要比这一字节序小,因此14为最大字节序。同时这两者是连在一起存入的,顺序不会颠倒,因为小端大端的存入都是以字节序的方式。

但上述储存是包含大量0的情况,当每一位上都不是0,最小依旧是16^0和16^1所在字节序,但最大对有符号的应该就是符号位所在序列,无符号的就是2^32的所在序列(可以把16进制位转换成2进制位来思考)

注:一个字节序代表 一个字节/八个比特 的存储序列

那么小端存储的含义即为i是以14 00 00 00存入的,大端存储的含义即为i是以00 00 00 14存入的

小端大端的存储只针对于2字节及以上的数据类型

大端小端究竟怎么存储是由硬件决定的

为什么有大端小端?
数据存储会有顺序问题,为了解决顺序问题使用了大小端存储的这种方式。

代码解决大小端判断问题

请见本文联合体讲解板块:结构体讲解

数据运算:

例1.下述代码输出结果是什么?

char a = -1;signed char b = -1;unsigned char c = -1;printf("a=%d,b=%d,c=%d", a, b, c);

在继续讲解前,我们首先需要知道字符型数据的取值范围

Signed char最高位是符号位

0表示正数,1表示负数;原码到反码,符号位不变

因此如果计算机中储存的补码是11111111,那么原码为10000001,即-1;同理存储的补码为10000001,那么原码为11111111,即-127;正数补码原码相同,存储的补码为01111111,结果为127

10000000由于不满足上述计算方法,因此计算机直接将他默认为-128,因此char的取值范围为 -128 ~ 127

无符号的最高位存放数据,代表2^7,因此无符号char的取值范围为0 ~ 255

 

-1的补码为11111111111111111111111111111111

char类型放不下,因此就进行截断。截断是从低位拿到高位(无论大小段存储),因此把最后8位11111111存入;进行%d打印时,会进行整型提升csdn表达式求值板块,补符号位数字,即1,结果即为补码形式的11111111111111111111111111111111,打印的是原码,即1000000000000000000000000000001,即-1

补码 ---> 原码 取反+1 原码 ---> 补码 取反+1

不是说原码到补码是 取反+1,补码到原码就是 -1取反

因此,a和b打印出来均为-1

由于无符号类型整型提升时没有符号位,因此直接补0,故c的补码为00000000000000000000000011111111(对于-1的截断上文已经提过),正数原码、补码相同,打印结果为255

注:数据截断发生在存入过程中,使用时在进行整型提升

例2.下述代码打印结果是?

signed char d = -128;printf(“%u”, d);

%u --- 打印无符号整数

10000000 00000000 00000000 10000000 --- -128的原码

11111111 11111111 11111111 01111111  --- -128的反码

11111111 11111111 11111111 10000000 +1即为+00000000 00000000 00000000 00000001

上文中的加1即为+00000000 00000000 00000000 00000001(加法的详细介绍在本文表达式求值板块:操作符讲解

相减即为逆向计算

例如11111111 11111111 11111111 10000000 - 1即为+(-1)

结果为11111111 11111111 11111111 01111111

-1的补码为 11111111 11111111 11111111 11111111

11111111 11111111 11111111 10000000 - 11111111 11111111 11111111 11111111

即为 1111111 11111111 11111111 10000000 + 1111111 11111111 11111111 11111111

最后8位,最后算出来为21111111,逢2进1,留下了01111111;前面不断逢2进1,因此先是全部变成0,但由于-1的补码中还有1没有加上去,因此最后结果为

11111111 11111111 11111111 01111111

数据2进制加减规则详细介绍:定点数的运算 —— 原码、补码的加减法运算

文章补充:数据加减运算是通过补码来进行的

10000000(signed char为有符号字符型)--- 截断

11111111 11111111 11111111 10000000 --- 整型提升

打印时打的是无符号字整数,因此计算机将11111111 11111111 11111111 10000000直接看作一个最高位为1的正数打印,补码原码相同

例3.下面代码的打印结果是?

unsigned int i;for (i = 9; i >= 0; i--);{printf("%u", i);}

先打印9 8 7 6 5 4 3 2 1 0,然后理应上是-1,但由于是无符号整型,所以结果为下

10000000 00000000 00000000 00000001 ---原码

11111111 11111111 11111111 11111110 ---反码

11111111 11111111 11111111 11111111 ---补码

无符号即是直接打印11111111 11111111 11111111 11111111,该数据-1为11111111 11111111 11111111 11111110还是大于0,一直大于等于0,会死循环

最终打印结果:

例4.下述代码的打印结果为?

char a[1000];int i;for (i = 0; i < 1000; i++){a[i] = -1 - i; //-1 -2 -3 -4 …… -999 -1000}printf("%d", strlen(a));

//strlen( )函数是求字符串的长度,关注的是字符串中\0(数字0,因为在计算机中,\0的ascII值为0)之前出现了多少个字符(即1字节的数据)

对于char这一类型,取值范围为-128~127(上文已经讲解过)

因此对于比 -129 更小的整型数据,是直接换成127,原因如下:

先从00000000开始,每+1,加到最大值,即127,即01111111,再+1,会变成10000000,上文已经说过,这个结果为-128,因此继续+1,即10000001,这是补码,换成原码结果为11111111,即-127,以此类推,最后一个数据为11111111(补码),即10000001(原码),即是-1

理解了上述过程,-1就是进行了逆向计算

因此到0的时候,总共有127+128 = 255 个字符(1字节数据)

1.-129如何变成127的呢?

-129为整型数据,在内存存放为10000000000000000000000010000001

取反+1

原码为 11111111111111111111111101111111

而这个数据如果要放进char类型中,进行截断,只留下了01111111,即127

2. 无符号字符型数据255如何加1变成0的呢?

255为无符号字符型数据的最大取值范围,补码为11111111,+1(00000000 00000000 00000000 00000001)以后,先是进行算数转换,就是00000000 00000000 00000000 11111111 + 00000000 00000000 00000000 00000001,再根据逢2进1的规则,最后补码留下了00000000 00000000 00000001 00000000,然后因为i + 1以后,还存放在i当中,即使i在给i赋值时根据算术转换原则依然是00000000 00000000 00000001 00000000,但i的类型依旧为无符号字符型变量,进行了强制类型转换,因此截断留下00000000,即是0.

浮点型在内存中的存储:

浮点数具体就是指小数点可以浮动的数值

整型数据表示的范围:limits.h中定义

浮点数表示的范围:float.h中定义

那为什么平时我们定义变量不需要引用这两个头文件呢?因为平时给变量初始化时,我们都是自己赋给它值,而这俩头文件里包含的数据都是整型数据最大值等等极限数值,因此平时使用不多

 

上面两图说明了整型数据和浮点型数据存储方式是不一样的

根据国际标准IEEE754,任意一个二进制浮点数都可以写成下述形式

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

(-1)^S 表示符号位,S为0,V为正数,S为-1,V为负数,最后结果需要表示成科学计数法的形式

 V = 5.0f ---> 101.0(5.0二进制表述形式)---> 1.01 * 2^2 ---> (-1)^0 * 1.01 * 2^2

即S=0,M=1.01,E=2

上例中为什么是2^2而不是10^2呢?

因为上述的101.0是二进制表达,因此是2^2;如果是5.0,那么才可以写成0.5 * 10^1

小数点后的位,权重是从2^(-1) 开始算,往后延申几位,负值减少几位

因此9.5的表示形式为 1001.1 (小数点前的是2^0 + 2^3 = 9 ;小数点后的是2^(-1) = 0.5

但是对于 9.6 这样的数据,2^(-1)为0.5,2^(-2)为0.25,2^(-3)为0.125,以此类推,最后就需要开辟非常非常多的0来满足0.1的需要

两张不同精度的浮点数

32位:

64位:

1≤M<2,也就是说,M可以写成1.xxxxxxx地形式,其中xxxxxxx表示小数部分。

IEEE754 规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以舍去,只保留后面的小数部分;等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。

以32位浮点数为例,留给M只有23位。将第一位的1舍去以后,等于可以保存24位有效数字 ---> 浮点数精度提升了

E为无符号整数,32位浮点数取值范围为0~255,64位浮点数取值范围为0~2047.但是,E是可以出现负数的

例如下图

因此存入内存是E的真实值必须再加上一个中间数,对于8位的E,这个中间数为127;对于11位的E,这个中间数为1023

假设上图的V为两种不同精度的类型,E最后在计算机中存储的值如下:

无论E真实值的正负,都需要加上这个中间值;且存储在计算机中的数值一律不为负

因此对于一个float型数据:5.5,在内存中的储存二进制表示如下:

在011后补0的原因:

省去了1,原本是1.011;如果是在011前补0,那么就会变成1.0000……011,与初始值不符

四个二进制位是一个16进制位,以此上述二进制表示成16进制的话为

4 0 b 0 0 0 0 0,即0x40 b0 00 00

注:float类型需要在数值后加上f,要不然计算机会把它视为double型,但在日常使用中,float i = 5.5,5.5依旧是单精度类型,这是由于前面的i是float型,进行了强制类型转换

指数E的取出分为三种情况

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

对于float型 0 10000001 01100000000000000000000,补1、减中间数,最后结果(-1)^0 * 1.01100000000000000000000 * 2^2

2.E全为0:

1.xxxxxxx * 2^(-126) 无限接近于0

3.E全为1:

1.xxxxxxx * 2^(128) 为无穷

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

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

相关文章

代码随想录算法训练营33期 第三十六天 |435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间 class Solution { public:static bool cmp(const vector<int>& a, const vector<int>& b){return a[0]<b[0];}int eraseOverlapIntervals(vector<vector<int>>& intervals) {sort(intervals.begin(), intervals.end()…

蓝桥集训之修理牛棚

蓝桥集训之修理牛棚 核心思想&#xff1a;贪心 先把所有牛棚合成一块木板然后将所有间隙大小求出 排序找到最大的n-1个总长度 - n-1个间隙 得到剩下n个木板总长度 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const i…

C#入门理解设计模式的6大原则

**设计模式的原则是指导设计模式创建和应用的基本原则&#xff0c;这些原则有助于创建灵活、可维护且可扩展的软件系统。**1. 单一职责原则&#xff08;Single Responsibility Principle, SRP&#xff09; 单一职责原则指出一个类应该只有一个引起它变化的原因。换句话说&…

Project Euler_Problem 172_Few Repeated Digits_动态规划

原题目&#xff1a; 题目大意&#xff1a;18位数里头&#xff0c;有多少个数&#xff0c;对于每个数字0-9&#xff0c;在这18位里面出现均不超过3次 111222333444555666 布星~~ 112233445566778899 可以~~ 解题思路&#xff1a; 动态规划 代码: ll F[19][3000000];void …

Spring AOP IOC

spring的优缺点 IOC集中管理对象&#xff0c;对象之间解耦&#xff0c;方便维护对象AOP在不修改原代码的情况下&#xff0c;实现一些拦截提供众多辅助类&#xff0c;方便开发方便集成各种优秀框架 紧耦合和松耦合 松耦合可以使用单一职责原则、接口分离原则、依赖倒置原则 …

融资融券交易与普通的股票交易相比,有哪些优势和劣势?

融资融券交易与普通交易相比有着很大的不同: 1、资金要求不同。 投资者在进行普通证券交易时&#xff0c;必须有足额的资金才能买入证券&#xff0c;必须有足额的证券才能卖出。 而投资者进行融资融券交易&#xff0c;不需要持有足额的资金。当投资者预测证券的价格将要上涨&…

DedeCMS 未授权远程命令执行漏洞分析

dedecms介绍 DedeCMS是国内专业的PHP网站内容管理系统-织梦内容管理系统&#xff0c;采用XML名字空间风格核心模板&#xff1a;模板全部使用文件形式保存&#xff0c;对用户设计模板、网站升级转移均提供很大的便利&#xff0c;健壮的模板标签为站长DIY自己的网站提供了强有力…

无线通信:多址(Multiple Access)方式

什么是多址方式 多址方式又叫多址接入方式或多址技术&#xff0c;是指在一个网络&#xff08;如移动通信的小区、无线局域网&#xff09;中&#xff0c;当多个用户接入网络时&#xff0c;解决如何高效地共享一个无线资源&#xff08;时间/频率/空间/载波&#xff09;的技术。 …

springboot发送邮件

很久之前就想写一个总结的&#xff0c;一直没写&#xff0c;今天刚好又碰见了发送邮箱验证码的需求&#xff0c;刚好记录一波 一.核心依赖如下&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-par…

docker部署opensearch —— 筑梦之路

OpenSearch 简介 •OpenSearch 是一款开源的分布式搜索引擎(从 ElasticSearch 特定版本分叉而来)&#xff0c;可以执行快速、可扩展的全文搜索、应用程序和基础设施监控、安全和事件信息管理、运营健康跟踪等用例。 •OpenSearch 具有多种功能和插件&#xff0c;可以帮助索引、…

谷歌推出适用于安卓设备的“Find My Device”网络,功能类似苹果Find My

谷歌今日推出了适用于安卓设备的“Find My Device”网络&#xff0c;其功能类似于苹果的“Find My”网络&#xff0c;旨在帮助用户定位丢失、被盗的安卓产品。 安卓的“Find My Device”网络可以利用数以亿计运行 Android 9 或更高版本的安卓设备&#xff0c;通过蓝牙信号追踪丢…

自动化运维(二十五)Ansible 实战过滤器插件和缓存插件

Ansible 支持多种类型的插件&#xff0c;这些插件可以帮助你扩展和定制 Ansible 的功能。每种插件类型都有其特定的用途和应用场景。今天我们一起学习 过滤器插件和缓存插件。 一、 过滤器插件&#xff08;Filter Plugins&#xff09; Ansible 过滤器插件&#xff08;Filter …

批量记录收支明细,高效记录当天的收支明细并查看每个支出占比,轻松掌握开销

在繁忙的现代生活中&#xff0c;我们时常因为琐碎的财务事务而分心。为了帮助您更好地管理财务&#xff0c;我们推出了这款智能财务助手&#xff0c;让您可以高效记录每天的收支明细&#xff0c;并轻松掌握每个支出的占比。从此告别混乱&#xff0c;让财务管理变得简单明了 第…

gym界面修改

资料&#xff1a;https://blog.csdn.net/weixin_46178278/article/details/135962782 在gym环境中使用mujoco的时候&#xff0c;有一个很难受的地方&#xff0c;界面上没有实时显示动作空间和状态空间状态的地方。 gym自己原始带的环境是用pygame画的图&#xff0c;所以在定义…

【前端】es-drager 图片同比缩放 缩放比 只修改宽 只修改高

【前端】es-drager 图片同比缩放 缩放比 ES Drager 拖拽组件 (vangleer.github.io) 核心代码 //初始宽 let width ref(108)//初始高 let height ref(72)//以下两个变量 用来区分是单独的修改宽 还是高 或者是同比 //缩放开始时的宽 let oldWidth 0 //缩放开始时的高 let o…

JWT重放漏洞如何攻防?你的系统安全吗?

大家好&#xff0c;我是石头~ 在数字化浪潮席卷全球的今天&#xff0c;JSON Web Token&#xff08;JWT&#xff09;作为身份验证的利器&#xff0c;已成为众多Web应用的首选方案。 然而&#xff0c;正如硬币有两面&#xff0c;JWT的强大功能背后也隐藏着潜在的安全风险&#xf…

2024mathorcup数学建模D题思路分析-量子计算在矿山设备配置及运营中的建模应用

# 1 赛题 D 题 量子计算在矿山设备配置及运营中的建模应用 随着智能技术的发展&#xff0c;智慧矿山的概念越来越受到重视。越来越多的 设备供应商正在向智慧矿山整体解决方案供应商转型&#xff0c;是否具备提供整体 解决方案的能力&#xff0c;也逐步成为众多矿山设备企业的核…

UVC摄像头在虚拟机Ubuntu16.04使用的正确姿势

前言&#xff1a;在Windows使用UVC摄像头是正常的&#xff0c;但在虚拟机Ubuntu中使用可以识别到&#xff0c; 但是一直没有数据出来&#xff0c;一度怀疑是摄像头不行&#xff0c;后来经过仔细研究&#xff0c;才发现是虚拟机usb设置有点问题。一、虚拟机USB设置USB 3.0,不然没…

【C++类和对象】上篇

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

数据仓库—ETL工具与技术:数据仓库的坚实基石

作为一名长期从事数据仓库领域的专业人士&#xff0c;我深知ETL&#xff08;Extract, Transform, Load&#xff09;工具和技术在构建和维护数据仓库中的核心作用。ETL不仅是数据流动的桥梁&#xff0c;更是确保数据质量和支持业务智能决策的关键环节。在这篇文章中&#xff0c;…