learn_C_deep_9 (汇编角度理解return的含义、const 的各种应用场景)
return 关键字
不知道我们大家是否有一个疑惑:我们下载一个大型游戏软件(王者荣耀),都要花几个小时去下载,但是一旦我们游戏连输,想要删除这个软件的时候,它仅仅只需要十几秒,这是为什么呢?今天我们就来带着这个疑惑,一起来解决这个问题。
计算机中,释放空间是否真的要将我们的数据全部清零?
在计算机中,释放空间并不一定要将其中的数据全部清零。释放空间,也就是删除文件,计算机并不会立即清零或删除文件的内容。实际上,计算机操作系统通常只是将这些文件对应的磁盘空间标记为可重用,然后在需要存储新的数据时将其覆盖。因此,即使删除了文件,它的内容可能仍然存在于硬盘或其他存储设备中,只要未被覆盖就可以恢复。
总结:当你删除一个文件时,计算机只需要简单地将文件所在的存储空间标记为可用,不需要进行实际的数据传输,因此删除数据的速度较快。
下面来看一段代码
#include <stdio.h>
char* show()
{char str[] = "hello world";return str;
}
int main()
{char* s = show();printf("%s\n", s);return 0;
}
这段代码主要涉及到两个问题:局部变量的生命周期和内存安全性。
首先,我们来看局部变量的生命周期。在函数 show() 中,变量 str 是定义在函数体内的局部变量。局部变量的生命周期只在函数体内,一旦函数执行完毕就会被销毁。因此,在 return str; 语句执行完毕之后,变量 str 所占用的内存空间就被释放了。
接着,我们看内存安全性的问题。在 show() 函数中,我们将作为返回值的变量 str 的地址返回给了调用者。由于变量 str 所在的内存空间已经被释放,因此返回的指针 s 指向的内存空间已经不再被保证安全。在 main() 函数中,我们调用了 printf() 函数输出了 s 所指向的内存空间中的字符串,由于该内存空间可能已经被其他程序或者系统使用,因此会导致未知的错误。这一点也是常说的“野指针”问题。
我们来详细了解一下其中的释放过程
总结:本代码中return语句不可返回指向"栈内存"的"指针",因为该内存在函数体结束时被自动销毁。
这里很奇怪呀?我们刚刚不是说函数调用完后会释放栈帧,里面的数据x经过printf函数应该就会被覆盖,但是我们这里为什么还能打印它呢? - 这里就要介绍一下return关键字
return 语句是 C 语言中的一个关键字,用于结束当前函数的执行并返回一个值或不返回值。在大多数情况下,return 语句用于向调用者返回一个函数执行结果。
return 语句有多种不同的用法和语法结构,其中最常见的用法是:
```
c return expression;
```
其中 expression 可以是一个常量、变量、表达式或者其他函数调用的返回值,这个值会成为函数的返回值被返回给调用者。
我们上面的代码返回的是x的值,函数栈帧内return关键字将x的值保存在寄存器中,通过寄存器将x的值带回给main函数中的y。如果是x的地址,它也会被返回,只不过不能打印其中的值。编译器会提出警告。
const 关键字
const是C语言中的一个关键字,它的作用是修饰变量,表示该变量的值是不可直接修改的。这意味着,使用const关键字声明的变量在程序运行期间一旦赋值就不能再被修改。const关键字可以用于修饰基本数据类型、结构体、指针等类型的变量。
使用const关键字有以下好处:
1. 程序的可读性更好,使用const关键字可以明确告诉其他程序员该变量是一个常量,不应该被修改。
2. 程序更加安全,使用const关键字可以避免在程序中意外地修改一个应该是常量的变量,提高了程序的健壮性。
3. 编译器可以利用const关键字优化程序,例如在一些情况下编译器可以将常量直接嵌入到代码中,提高了程序的执行效率。
const 修饰的只读变量 - - - 不可直接被修改!
不可以直接被修改,但可以被间接修改 - 通过地址进行修改
结论:const修饰的变量并非是真的不可被修改的常量。
const修饰的变量,可以作为数组定义的一部分吗?
const int n = 100;
int arr[n];
这里可以看我写的另一篇文章,里面有介绍到。
总结:在vs2013(标准C)下直接报错了,但是在gcc(GNU扩展)下,可以。但我们一切向标准看齐,不可以。
const只能在定义的时候直接初始化,不能二次赋值。为什么?
const关键字的作用是告诉编译器该变量是一个常量,不应该被修改。因此,使用const关键字声明的变量在程序运行期间一旦赋值就不能再被修改。
为了让编译器能够实现这个目标,const关键字在编译时会对该变量进行一些优化,使得该变量的值在程序运行期间不可修改。如果允许在程序运行期间对该变量进行二次赋值,那么编译器就无法保障该变量的值不会被修改,这与const关键字的含义相违背。
因此,const只能在定义的时候直接初始化,不能二次赋值的原因是为了保证程序的健壮性和安全性。如果确实需要在程序运行期间动态地修改一个变量的值,应该使用普通的变量而不是使用const修饰的变量。
const修饰指针
先来介绍一下左值和右值的概念
在计算机编程中,左值(lvalue)和右值(rvalue)是表达式的两种类型。
左值表示的是被赋值的对象,可以出现在“=”的左边,也可以在表达式的任何一个操作数中。左值可以出现在多个操作中,并且能够被改变。
右值表示的是一个可以赋值给左值的值,右值可以出现在表达式的任何一个操作数中,但是不能被改变。右值通常是一个临时值,用于计算表达式,并且当表达式执行完毕后,其值就会被丢弃。
指针变量也存在左值和右值。
在C语言中,指针是一种特殊的变量,它存储的是一个内存地址,可以用来访问那个地址中存储的数据。在定义指针变量时,我们可以使用const关键字来决定指针和指针指向的数据是否可以被修改。
1. const int* p;
这里的const作用于指针指向的数据,表示p指向的数据是不可修改的。也就是说,我们可以通过p指针读取这个常量数据,但是不能通过p指针修改这个数据。比如:p本身可以被修改(比如p++),但是p指向的int类型变量是不可修改的(比如*p=10是不合法的)。
2. int const* p;
这个定义和上面的定义是等价的,const关键字位置不同但含义相同。
3. int* const p;
这里的const作用于指针本身,表示p指针本身是不可修改的。也就是说,我们不能通过改变p指针的值来让它指向其他的地址,但是可以通过p指针修改这个地址中存储的数据。比如:p本身不可以被修改(比如p++是不合法的),但是p指向的int类型变量是可以被修改的(比如*p=10是合法的)。
4. const int* const p;
这个定义中有两个const关键字,一个作用于指针本身,一个作用于指针指向的数据。表示p指针本身和p指向的数据都是不可修改的,也就是说,p指针只能指向某一块地址,而且这块地址中存储的数据也不能被修改。比如:p本身不可以被修改(比如p++是不合法的),并且p指向的int类型变量也是不可修改的(比如*p=10是不合法的)。
const int* p1 = &a;
int* q1 = p1;
这里将const int*类型的指针p1赋值给了int*类型的指针q1,这样做是不安全的。因为p1指向的是一个不可修改的常量int类型变量,如果通过q1指针去修改p1所指向的变量,就会引发未定义行为。正确的做法是将指针类型强制转换为非const类型,即: int* q1 = (int*)p1;
int* const p2 = &b;
int* q2 = p2;
这里将int* const类型的指针p2赋值给int*类型的指针q2,这样做是安全的。因为p2指向的是一个可以修改的int类型变量,同时p2本身也是不可修改的。而且,将const类型的指针赋值给非const类型的指针也是安全的。所以这段代码是没有问题的,不需要做改动。
const修饰函数的参数
在C语言中,我们也可以使用const关键字来修饰函数的参数,这表示函数不会修改被修饰的参数的值。 函数中的参数可以分为形参和实参,形参是函数中定义的变量,实参是函数调用时传递给函数的值。使用const关键字修饰形参时,表示函数中不能修改这个形参的值。如果函数试图修改被const修饰的形参,编译器会报错。
下面是一个使用const修饰函数参数的例子:
void print_array(const int* arr, int n) {for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n"); }int main(void) {int arr[] = { 1, 2, 3, 4, 5 };print_array(arr, 5);return 0; }
在这个例子中,print_array函数的第一个参数是const int*类型,表示这个指针指向的是一段不可修改的内存,函数中不能修改这段内存对应的值。第二个参数是普通的int类型,表示数组的长度。 在函数内部,我们使用了一个for循环来遍历数组,并使用printf函数打印数组中的每个元素。 因为我们将第一个参数声明为const int*类型,所以在函数中不能修改这个指针所指向的值。如果函数尝试修改这个指针所指向的值,编译器会报错。
这有助于保护数组中的值不被意外修改,提高程序的健壮性。
函数在传参的时候有没有形成临时变量?
在C语言中,函数参数传递采用的是值传递或者地址传递方式。当我们调用函数时,会将实参的值复制一份,然后传递给函数,而函数中定义的形参则是一个新的变量。这个过程中,确实会生成一个临时变量来存储实参的值。
拜拜!!!
相关文章:
learn_C_deep_9 (汇编角度理解return的含义、const 的各种应用场景)
return 关键字 不知道我们大家是否有一个疑惑:我们下载一个大型游戏软件(王者荣耀),都要花几个小时去下载,但是一旦我们游戏连输,想要删除这个软件的时候,它仅仅只需要十几秒,这是为…...
基于深度学习的OCR技术
随着数字化时代的到来,图片识别技术越来越受到人们的关注。其中,OCR技术作为图片处理的一个重要分支,可以将扫描的图片进行自动识别和分类,极大地提高了工作效率。本文将介绍有道实况OCR技术的相关内容,帮助读者更好地…...
『python爬虫』09. bs4实战之下载精美壁纸(保姆级图文)
目录 爬取思路代码思路1.拿到主页面的源代码. 然后提取到子页面的链接地址, href2.通过href拿到子页面的内容. 从子页面中找到图片的下载地址 img -> src3.下载图片 3. 完整实现代码总结 欢迎关注 『python爬虫』 专栏,持续更新中 欢迎关注 『python爬虫』 专栏&…...
【Linux学习】多线程——线程控制 | 线程TCB
🐱作者:一只大喵咪1201 🐱专栏:《Linux学习》 🔥格言:你只管努力,剩下的交给时间! 线程控制 | 线程TCB 🧰线程控制🎴线程创建🎴线程结束…...
Node 10 接口
接口 简介 接口是什么 接口是 前后端通信的桥梁 简单理解:一个接口就是 服务中的一个路由规则 ,根据请求响应结果 接口的英文单词是 API (Application Program Interface),所以有时也称之为 API 接口 这里的接口指的是『数据接口』&#…...
大型互联网企业大流量高并发电商领域核心项目已上线(完整流程+项目白皮书)
说在前面的话 面对近年来网络的飞速发展,大家已经都习惯了网络购物,从而出现了一些衍生品例如:某宝/某东/拼夕夕等大型网站以及购物APP~ 并且从而导致很多大型互联网企业以及中小厂都需要有完整的项目经验,以及优秀处理超大流量…...
汇编语言学习笔记六
flag 寄存器 CF:进位标志位,产生进位CF1,否则为0 PF:奇偶位,如010101b,则该数的1有3个,则PF0,如果该数的1的个数为偶数,则PF1。0也是偶数 ZF:在相关指令执行后(运算和逻辑指令,传送指…...
多商户商城系统-v2.2.3版本发布
likeshop多商户商城系统-v2.2.3版本发布了!主要更新内容如下 新增 1.用户端退出账号功能 优化 1.平台添加营业执照保存异常问题 2.平台端分销商品优化-只显示参与分销的商品 3.优化订单详情显示营销价格标签 4.平台交易设置增加默认值 5.种草社区评论调整&a…...
科研人必看入门攻略(收藏版)
来源:投稿 作者:小灰灰 编辑:学姐 本文主要以如何做科研,日常内功修炼,常见科研误区,整理日常‘好论文’四个部分做以介绍,方便刚入门的科研者进行很好的规划。 1.如何做科研 1.1 选方向 当我…...
第5章 循环和关系表达式
1. strcmp()//比较字符串数组是否相等| string 可以直接用“”来判断 char word[5] "aaaa"; strcmp(word,"aaab");//相同输出0,不同输出1; 2. 延时函数 #include<ctime>float sec 2.3;long delay sec*CLOCKS_PER_SEC;long start c…...
Scalable Vector Graphics (SVG)中的svg、clipPath、mask元素
Scalable Vector Graphics (SVG)是一种用于描述二维向量图形的XML基础标记语言。使用SVG可以实现丰富的图形效果,而不需要像使用位图那样考虑分辨率和像素密度的问题,可以在不同设备上展示出相同的高质量图像。 在SVG中,除了基本形状如circl…...
Java基础(十五)集合框架
1. 集合框架概述 1.1 生活中的容器 1.2 数组的特点与弊端 一方面,面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用数组存储对象方面具有一些弊端,而Java 集合…...
安装gitea
1、安装包(gitea-1.13.1-linux-amd64)上传到服务器,并添加执行权限 链接:https://pan.baidu.com/s/1SAxko0RhVmmD21Ev_m5JFg 提取码:ft07 chmod x gitea-1.13.1-linux-amd64 2、执行 ./gitea-1.13.1-linux-amd64 web…...
Java异常处理传递规范总结
java 异常分类 Thorwable类(表示可抛出)是所有异常和错误的超类,两个直接子类为Error和Exception,分别表示错误和异常。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常, 这两种异常有很大的区别…...
2d俯视视角游戏,可以切换多种枪械
文章目录 一、 介绍二、 人物移动、鼠标控制转向三、子弹脚本四、子弹随机抛壳五、 爆炸特效六、 发射子弹七、 子弹、弹壳对象池八、 散弹枪九、 火箭弹、发射火箭十、 下载工程文件 一、 介绍 2d俯视视角游戏。 人物视角跟随鼠标移动 多种枪械 抛壳效果 多种设计效果 对象池…...
大四的告诫
保研/考研方向就绩点,(各种)比赛,(考研)刷题为主 工作就算法(比赛),项目,实习为主 👂 LOCK OUT - $atori Zoom/KALONO - 单曲 - 网易云音乐 &…...
滚珠螺杆在设备上的应用
滚珠螺杆跟直线导轨一样,是很多机械设备上不可或缺的重要部件,它是确保机器能够具备高加工精度的前提条件,因此本身对于精度的要求也相当地高。今天,我们就来了解一下滚珠螺杆在不同设备上的应用吧! 1、大型的加工中心…...
Day41线程同步
线程同步 案例:三个窗口卖100张票 //定义一个类SellTicket实现Runnable接口,定义成员变量100张票 public class SellTicket implements Runnable{private int tickets 100;//重写run方法Overridepublic void run(){while (true){ //没有票后&…...
设计模式之享元模式
参考资料 曾探《JavaScript设计模式与开发实践》;「设计模式 JavaScript 描述」享元模式设计模式之享元模式Javascript 设计模式 - 享元模式 定义 享元模式的英文叫:Flyweight Design Pattern。享元设计模式是用于性能优化的模式,这种设计…...
【GAMES101】05 Rasterization(Triangles)
光栅化过程:将一系列变换后的三角形转换为像素的过程。 三角形在图形学中得到很多的应用。 最基础的多边形(边数最少)。任何多边形都可以拆成三角形。性质:三角形内部一定是平面的。三角形内外部定义非常清楚。定义三个顶点后&a…...
13. Pod 从入门到深入理解(二)
本章讲解知识点 Pod 容器共享 VolumeConfigMapSecretDownward APIEmptyDir VolumeHostPath Volume1. Pod 容器共享 Volume 1.1. Volume 的背景及需要解决的问题 存储是必不可少的,对于服务运行产生的日志、数据,必须有一个地方进行保存,但是我们的容器每一次重启都是“恢复…...
ORBBEC(奥比中光)AstraPro相机在ROS2下的标定与D2C(标定与配准)
文章目录 1.rgb、depth相机标定矫正1.1.标定rgb相机1.2.标定depth相机1.3.rgb、depth相机一起标定(效果重复了,但是推荐使用)1.4.取得标定结果1.4.1.得到的标定结果的意义 1.5.IR、RGB相机分别应用标定结果1.5.1.openCV应用标定结果1.5.2.ros…...
常量与变量:编程中重要的两种数据类型
常量与变量 在编程中,我们常常需要存储一些数据。这些数据有些是恒定不变的,有些却是可以随时变化的。对于恒定不变的数据,我们称之为常量;对于可以变化的数据,我们则称之为变量。这两种数据类型在程序中非常重要&…...
( 数组和矩阵) 287. 寻找重复数 ——【Leetcode每日一题】
❓287. 寻找重复数 难度:中等 给定一个包含 n 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。 你…...
【学习笔记】「JOISC 2022 Day2」复制粘贴 3
看了正解。我觉得很厉害。虽然用减枝水过去了。 区间 d p dp dp。但是这个转移怎么看都不是 O ( 1 ) O(1) O(1)的。 border \text{border} border 那么 trick \text{trick} trick应该都能看出来。能进行剪切操作当且仅当 s [ l , p ] s [ q , r ] s_{[l,p]}s_{[q,r]} s[l,p]…...
武忠祥老师每日一题||定积分基础训练(三)
常用的基本不等式: sin x < x < t a n x , x ∈ ( 0 , π 2 ) \sin x<x<\ tan x,x\in(0,\frac{\pi}{2}) sinx<x< tanx,x∈(0,2π) e x ≥ 1 x , x ∈ ( − ∞ , ∞ ) e^x\ge1x,x\in(-\infty,\infty) ex≥1x,x∈(−∞,∞) x 1 x ≤ ln …...
Docker安装常用软件-Apollo(有问题)
零:apollo概念介绍 官网网站:GitHub - apolloconfig/apollo: Apollo is a reliable configuration management system suitable for microservice configuration management scenarios. gitee网址:mirrors / ctripcorp / apollo GitCode …...
f(x)与|f(x)|,f ‘ (x),F(x)常见关系。
1.f(x)与|f(x)|关系。 1.连续关系。(f(x)在"[a,b]上连续" > |f(x)|在"[a,b]连续") ①如果f(x)在[a,b]上连续。则|f(x)|在[a,b]上连续. (因为f(x)在x0的连续点>x0必为|f(x)|的连续点) 注:”[a,b]连续“包括&#…...
今天面了一个来字节要求月薪23K,明显感觉他背了很多面试题...
最近有朋友去字节面试,面试前后进行了20天左右,包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说,80%的人都会栽在第一轮面试,要不是他面试前做足准备,估计都坚持不完后面几轮面试。 其实&…...
如何使用二元三次回归分析建立预测模型?(分析、原理、代码示例)
二元三次回归是一种用于建立两个自变量与一个因变量之间关系的回归模型,常用于数据分析和预测。下面我会更详细地解释一下二元三次回归的原理、分析和示例代码。 1、原理 二元三次回归分析用多项式回归建立预测模型,其中包括两个自变量(通常…...
六安网络营销/郑州专业seo推荐
转自:http://developer.51cto.com/art/201011/235040.htm Mono一直到现在的2.8已经完全可以胜任一些比较小的项目了,但相关的开发文档与教程一直比较匮乏,中文材料更是屈指可数。虽然Mono与.net很多类库都是通用的,但Mono仍然有为…...
网站建设20推广/最新军事新闻 今日 最新消息
随机数的不重复选择就是从n个数中随机选取m(m<n)个数。在本文中,我们用Java来实现。因此我们先介绍Java的相关知识。 在Java中,Java.util.Set接口和Java.util.List接口一样,都是继承自Java.util.Collection接口。但是两者有不同的特点&am…...
做网站用哪个服务器好/seo推广网络
《读懂一本书:樊登读书法》_精选读后感500字我们为何要读书?这个问题好回答,也不好回答!我们读书带着目的?或者不带目的?都不重要!重要的是能够使自己成长和进步,只有这样才能积累“…...
MAC怎么做网站/seo首页排名优化
Python是一门更注重可读性和效率的语言,尤其是相较于Java,PHP以及C这样的语言,它的这两个优势让其在开发者中大受欢迎。诚然,它有点老了,但仍是80后啊 —— 至少没有 Cobol 或者 Fortran 那么老。而且,如果…...
可以做网站AB测的软件/自建站怎么推广
0. UDP通信特点 udp 是一个面向无连接的,不安全的,报式传输层协议,udp 的通信过程默认也是阻塞的。 UDP通信不需要建立连接 ,因此不需要进行 connect () 操作UDP通信过程中,每次都需要指定数据接收端的IP和端口&…...
wordpress主题自媒体一号/做网络推广为什么会被抓
原文:https://www.jianshu.com/p/3004e5999be4 解决了关于补码扩展位宽时符号位一直补最高位的疑问 看3.补码的本质 1、在计算机内,有符号数有3种表示法:原码、反码和补码 有符号数在计算机中存储,用数的最高位存放符号, 正数为0…...