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

news2024/11/21 1:33:43

目录

版本差异:

数据类型:

进制表示:

大小端储存:

数据运算:

浮点型在内存中的存储:


版本差异:

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.coloradmin.cn/o/1593687.html

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

相关文章

深度学习图像处理基础工具——opencv 实战2 文档扫描OCR

输入一个文档&#xff0c;怎么进行文档扫描&#xff0c;输出扫描后的图片呢&#xff1f; 今天学习了 opencv实战项目 文档扫描OCR 问题重构&#xff1a;输入图像 是一个含有文档的图像——> 目标是将其转化为 规则的扫描图片 那么怎么实现呢&#xff1f; 问题分解&#…

leetcode.45题:跳跃游戏II

Leetcode.45题&#xff1a;跳跃游戏II /* 题意的理解&#xff1a; nums[0] 只能跳 1 ~ nums[0]步 依次类推&#xff1a;从nums[0] - nums[n - 1] 最少需要多少步数 nums 2 3 1 1 4 nums[0] 2,初始只能跳 1/2步&#xff0c;如跳1步&#xff0c;达到nums[1] 而nums[1] 3,顾第二…

Python学习笔记22 - 文件操作

文件读写的原理 文件读写的操作 常用的文件打开模式 文件对象的常用方法 with语句&#xff08;上下文管理器&#xff09;

kubekey 离线安装harbor、k8s、kubesphere

目录 参考文献 了解kubekey 英文和中文 前提条件 部署准备 下载kubukey 离线包配置和制作 配置离线包 制作离线包 离线安装集群 复制KubeKey 和制品 artifact到离线机器 创建初始换、安装配置文件 安装镜像仓库harbor 初始化harbor 项目 修改配置文件 安装k8s集…

一.表单校验

为什么要表单验证&#xff1f; 是为了减轻服务器的压力&#xff0c;让用户体验更好&#xff0c;保证输入的数据符合要求 常用的表单验证 日期格式 表单元素是否为空 用户名和密码 E-mail 地址 身份证号码 实现验证的思路 问题&#xff1a;当输入的表单数据不符合要求时&…

内网渗透-windows权限维持的方法

windows权限维持的方法 文章目录 windows权限维持的方法一、影子账户二、粘滞键后门三、logon scripts后门五、注册表自启动后门六、屏幕保护程序后门七、计划任务后门八、服务自启动后门九、黄金票据十、白银票据十二、bitsadmin十五、CLR劫持 一、影子账户 1.使用如下命令创…

你真的会处理python代码异常吗?

Python 使用称为异常(exception&#xff09;的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时&#xff0c;它都会创建一个异常对象。如果你编写了处理该异常的代码&#xff0c;程序将继续运行&#xff1b;如果你未对异常进行处理&#xff0c;程序将停…

CodeGemma: Open Code Models Based on Gemma

最近几天&#xff0c;对大模型生成代码的能力比较感兴趣&#xff0c;特此学习了一下大模型怎么在IDE上进行&#xff0c;自动补全你想要的代码。 大模型源码理解-以Gemma为例子 最近也在使用阿里的通义灵码&#xff0c;感觉还挺好用的。通义灵码 摘要&#xff1a; CodeGemma基…

Linux ARM平台开发系列讲解(QEMU篇) 1.2 新添加一个Linux kernel设备树

1. 概述 上一章节我们利用QEMU成功启动了Linux kernel,但是细心的小伙伴就会发现,我们用默认的defconfig是没有找到设备树源文件的,但是又发现kernel启动时候它使用了设备树riscv-virtio,qemu,这是因为qemu用了一个默认的设备树文件,该章节呢我们就把这个默认的设备树文件…

【设计模式学习】单例模式和工厂模式

꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转…

明月三千里许红:25年磨一剑 拒绝网红式短期主义

这是一个关于明月三千里烤肉品牌如何在25年企业经营风口浪尖中&#xff0c;寻求长久生存和发展的故事&#xff1b;也是一个关于明月三千里烤肉品牌如何在25年中追逐流量的同时&#xff0c;不失去初心和品质的深度思考&#xff01; 在当今快速变化的餐饮市场中&#xff0c;淄博烤…

【CSS】利用Vue实现数字翻滚动画效果

利用Vue实现数字翻滚动画效果 在很多数据可视化的需求中&#xff0c;动态呈现数据变化是一个常见且具有较强视觉冲击力的手段&#xff0c;尤其是数字的实时变化。今天我们将探讨如何使用 Vue.js 和 CSS3 来实现数字的翻滚动画效果&#xff0c;即模拟真实物体在Z轴上翻动的效果…

使用cmake进行打包,包含可执行程序和动态依赖库

平常代码开发中&#xff0c;有时候需要将写的程序打包成压缩包放到目标设备上进行运行测试。用CMake管理工程&#xff0c;实现使用make -jnproc package指令可以将工程进行打包&#xff0c;可执行文件存储在bin文件夹中&#xff0c;依赖库存储在lib文件夹中。 示例 1.工程目录结…

选择自动化工具是一个关键的决策过程

好的自动化软件测试工具&#xff0c;不仅可以有效的缩短全生命周期的交付周期&#xff0c;还可以提高测试的有效性&#xff0c;还可以保证更好的高质量的交付。工具的选型是一项重要的决策过程&#xff0c;工具的采用涉及到企业的效率、成本和长期发展。 1、需求分析 确组织希…

云服务器web环境之mariadb

1.安装mariadb服务 yum install mariadb-server 启动mariadb服务 systemctl start mariadb.service 输入mysql就能使用数据库了。 2.服务相关操作 systemctl stop mariadb.service systemctl restart mariadb.service 2.配置开机自启动 systemctl enable mariadb.serv…

python--5--len()

学习目标&#xff1a; len()#range&#xff0c;list,列表、元组,字符串,包括空格,返回字典的“键值对”个数 学习内容&#xff1a; len()#range&#xff0c;list,列表、元组,字符串,包括空格,返回字典的“键值对”个数 len()--返回对象长度 len()#range&#xff0c;list,列…

matlab学习(三)(4.9-4.15)

一、空域里LSB算法的原理 1.原理&#xff1a; LSB算法通过替换图像像素的最低位来嵌入信息。这些被替换的LSB序列可以是需要加入的水印信息、水印的数字摘要或者由水印生成的伪随机序列。 2.实现步骤&#xff1a; &#xff08;1&#xff09;将图像文件中的所有像素点以RGB形…

华为海思数字芯片设计笔试第四套

声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨论…

1688采集API 接口:轻松实现电商数据采集与官方订单API接口对接

各大平台电商软件大全&#xff0c;优质服务 1688采集API接口&#xff0c;一款助力电商从业者轻松实现阿里巴巴与1688平台商品数据采集接口&#xff0c;在数据为王的电商时代&#xff0c;掌握高效的采集与管理技能&#xff0c;无疑是成功的一把钥匙。 功能概述&#xff1a; 1.…

神经射频脉冲术,破解疼痛之锁

一位十余年糖尿病病史的患者&#xff0c;右足开始出现疼痛和麻木的症状三个多月&#xff0c;给他的生活带来了极大的困扰。他曾在多家医院就诊&#xff0c;但治疗效果并不理想。直到他走进了北京精诚博爱医院&#xff0c;这里为他带来了希望和转机。 经过详细的检查&#xff0c…