鹏哥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,一经查实,立即删除!

相关文章

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 …

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

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

springboot发送邮件

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

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

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

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

在繁忙的现代生活中&#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…

字节码文件的组成

字节码文件的组成 字节码文件的组成1 以正确的姿势打开文件2 字节码文件的组成2.1 基本信息2.2 常量池2.3 字段2.4 方法2.5 属性 3 字节码常用工具3.1 javap3.2 jclasslib插件3.3 Arthas 4 字节码常见指令 字节码文件的组成 1 以正确的姿势打开文件 字节码文件中保存了源代码…

Git 解决分支冲突

一、前言 一直习惯于 add commit push 的三步走&#xff0c;偶然间看到了一个评论说在 push 之前还有一个 pull&#xff0c;小小的疑问就埋在了我的心里。于是我就先了解了 pull 的工作原理&#xff0c;就是先拉取代码&#xff08;fetch&#xff09;再合并分支&#xff08;mer…

matlab使用教程(42)—常见的二维图像绘制方法

这个博客用于演示如何在 MATLAB 中创建曲线图、条形图、阶梯图、误差条形图、极坐标图、针状图、散点图。 1.曲线图 plot 函数用来创建 x 和 y 值的简单线图。 x 0:0.05:5; y sin(x.^2); figure plot(x,y) 运行结果&#xff1a; 线图可显示多组 x 和 y 数据。 x 0:0.05:…

旧版本jquery升级新版本后如何处理兼容性问题

前言 最近项目在漏洞扫描过程中发现现在的jquery版本受多个跨站点脚本漏洞影响&#xff0c;需要升级jquery版本。 1、首先下载高版本的jquery&#xff0c;我这里升级的是3.6.0 2、对应的bootstrap版本也要升级&#xff0c;这里升级的是3.3.7 本来以为替换完这两个文件后&#…

STM32H7定时器TIM1-TIM17中断、PWM实现

STM32H7定时器TIM1-TIM17中断、PWM实现 高级定时器硬件框图定时器模式时基输出PWM定时器输入捕获 TIM1-TIM17的中断配置TIM1-TIM17的PWM输出 STM32H7 支持的定时器有点多&#xff0c;要简单的区分下。STM32H7 支持 TIM1-TIM8&#xff0c;TIM12-TIM17 共14 个定时器&#xff0c;…

Traefik不同版本之间的差异?

Traefik 是一款流行的开源反向代理和负载均衡器&#x1f504;&#xff0c;它被广泛用于容器化&#x1f4e6;和微服务架构&#x1f310;中。从其首次发布以来&#xff0c;Traefik 经历了多个版本的更新&#xff0c;每个版本都带来了重要的新特性和改进&#x1f6e0;️。在本文中…

GitHub repository - Watch - Star - Fork - Follow

GitHub repository - Watch - Star - Fork - Follow References 眼睛图标旁边写着 Watch 字样。点击这个按钮就可以 Watch 该仓库&#xff0c;今后该仓库的更新信息会显示在用户的公开活动中。Star 旁边的数字表示给这个仓库添加 Star 的人数。这个数越高&#xff0c;代表该仓库…

【数据结构】习题之链表的回文结构和相交链表

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《数据结构》 &#x1f389;前路漫漫亦灿灿 前言 今日的习题是关于链表的&#xff0c;分别是链表的回文结构和相交链表的判断。 链表的回文结构 题目为&#xff1a;链表的回文结…

sysbench MySQL性能测试

目录 1. QPS&&TPS 1.1 数据库启动到现在的运行时间(秒) 1.2 查询量 1.3 status命令直接显示出QPS 1.4 每秒输出数据库状态(累加) 2. sysbench 测试工具 3. OLTP MySQL测试 3.1 普通参数 3.2 支持的lua脚本 3.3 脚本参数 3.4 测试数据准备 3.5 进行测试 3.…