你真的了解C语言吗 (深度剖析C语言第一期)_c语言深度 剖析第一-程序员宅基地

技术标签: 2024年程序员学习  c语言  开发语言  

1.在没有加载到内存之前,程序在哪?

2.为什么所有的程序运行都要加载到内存当中?

通过学习我们可以知道,程序在没有加载到内存的时候放在硬盘,至于为什么程序运行的时候都必须放入硬盘是因为能提高运行效率,让程序更快运行。在此,我们需要了解一些硬件知识。**数据在传输的过程中大体要经历四个步骤,先由输入设备加载到内存,再通过CPU的处理后放到内存,最后刷新至输出设备。**我们先做了解,后续会再次学习冯诺依曼。

变量的声明和定义

变量的本质就是在内存中开辟一块空间用内存保存数据,处于代码块内的变量都是临时变量,运行的时候在内存栈区开辟。为什么定义变量本质都在内存开辟?因为变量在运行的时候才会开辟,而在程序运行之前都会加载到内存。当开辟变量的时候程序已经被加载到内存了。

定义是开辟空间,声明可以理解为告知。定义就是开辟变量,只能定义一次,声明可以声明多次。

关键字auto

通常用来修饰局部变量,该变量只在该代码块内有效,但是随着编译器的进步,auto已经可以被省略了。同样,我们通过程序来验证一下。

由此可见,当auto修饰局部变量的时候,程序是可以运行的,此时auto可以省略。由于auto关键字是年代很久远,我们现阶段基本不用,了解一下即可。

关键字register

什么是存储分级

首先我们需要了解具有存储能力的设备,寄存器,cache,内存,硬盘,软盘……距离CPU越近的存储单元,效率越高,单价成本越高。距离CPU越远的存储单元,效率越低,单价成本越低。对于任何一种硬件而言,它都充当这自己上游硬件的缓存,因此,CPU访问数据的时候以最小的成本达到最高的效率。

register修饰变量

register修饰变量就是尽量将该变量放入CPU的寄存器中,从而达到提高效率的目的。 哪些变量适合用register修饰呢?

1.局部变量,之所以不使用全局变量是一旦将全局变量放入寄存器中,它的作用域是整个工程,生命周期很长使得CPU寄存器被长时间占用。

2.不会被写入的变量。由之前所提及的冯诺依曼规则我们可以知道,数据写入将会被重新回写到内存中,然后重新加载。这样register就没有太大的意义。

3.高频被读取的变量。如果一个变量开辟空间时放在CPU的寄存器里面,那么我们读取变量的时候直接通过寄存器读取,直接通过CPU寄存器读取的效率是极高的。

那我们来思考一下,当我们用register修饰变量的时候,是在寄存器里面开辟的,能找到它的地址吗?想法归想法,写个程序测试一下。

实践证明,编译器报错,register修饰的变量在很多时候是在寄存器中开辟了一块空间而并非是在内存中开辟,而地址是内存上的地址,由此该变量是没有地址的,也是就不能通过取地址符号来找地址。

static关键字

多文件工程

首先我们可以思考一个问题,如果我们在一个工程里面创建两个源文件并将一个源文件里调用存放在另一个文件里的函数,会怎么样呢?是否会打印“别睡啦,快来和小生一起学习吧”呢?我们来测试一下:

程序运行可以发现,在同一个工程的两个不同源文件中,在一个文件里调用另一个文件中的函数是完全可以的,全局变量的作用域是整个工程,那我们如果在一个文件中使用另一个文件中的全局变量可以吗?我们来试一下。

**在此,我们需要用一个extern关键字来声明变量,注意我们这里是声明,并没有开辟空间。**因此我们在重拾C语言.c文件中只能用extern int num;声明该变量来自其他源文件。而不能用extern int num = 5;根本上说声明是没有开辟空间的但是存放变量是需要空间,因此这种写法是错误的。

但是如果项目比较大,文件一多,难道我们每个文件之前都需要声明外部变量或者函数吗?这样维护成本会变得极高,因此我们可以把所需外部函数、全局变量等放入一个新的头文件,可以减少维护成本。头文件基本上是被多个源文件包含,头文件可能会被重复包含,我们需要防止头文件被包含,我们可以在头文件之前加入#pragma once,那我们头文件一般包括什么呢?可以包含所有变量的声明,所有函数的声明,所有所需要的系统自带的头文件,#define ,typedef ,struct结构体等。

之前我们调用其他文件的函数时系统并未报错,但是为了让程序更加严谨,我们应该给来自外部的函数同样进行声明,那函数应该如何声明呢?函数的声明就是把函数的返回值函数的名称和函数的形参列表全部写上,不用写函数体。函数的定义本质也是在内存里开辟空间,变量保存的是数据,函数保存的就是代码,在上面这个问题,我们也可以用extern void show();来声明来自外部的函数。我们通过一个图来看一下:

通过上面的学习,我们知道,全局变量可以跨文件访问,函数也可以跨文件访问。但是在实际的应用当中,我们可能在某些时候不想让全局变量或者函数跨文件访问。这里我们就正式进入我们的主题——关键字:static。当我们用static修饰之前的全局变量num的时候我们改一下程序运行一下:

我们发现vs编译器报错,由此我们可以得出,static修饰全局变量的时候表示该变量只在本文件内被访问,不能被外部其他文件直接访问。那我们也可以猜想,当static修饰函数的时候,该函数是否也只是在该文件内可以被直接调用呢?我们可以试一下。

和原来的想法一样,直接报错哈哈,由此我们也可以得出一个结论,当static修饰函数的时候,该函数只能在本文件访问,不能在其他的文件内直接访问。但是可以通过嵌套的方式来访问。哈哈,是不是挺有趣的,我们来看一下:

因此我们以上的陈述是不能直接访问,但是可以通过函数嵌套的模式来间接访问。哈哈,确实挺有意思的。通过这个程序往深里面剖析,static是一个提供安全保护和项目维护的关键字。我们可以通过static把我们写的东西封装起来,用一个大函数包含, 这样就限制了他人对我们程序的修改,降低了暴露的接口,提高了程序的安全性,是不是很有意思呢?

我们再来看看下面这两个程序的对比:

**先看程序1:**

//程序1
#include <stdio.h>
static void fun()
{
int i = 0;
i++;
printf("%d ",i);
}
int main()
{
for(int i = 0 ; i <= 10; i++)
{
fun();
}
return 0;
}

直接看结果:

**再看程序2:**

//程序2
#include <stdio.h>
static void fun()
{
static int i = 0;
i++;
printf("%d ",i);
}
int main()
{
for(int i = 0;i <= 10 ;i++)
{
fun();
}
return 0;
}

直接看结果:

局部变量具有临时性,函数调用开辟空间并初始化,函数结束后释放空间,因此再第一个程序中,每次调用fun函数的时候每次都要为i开辟一块内存存放,然后函数结束后就销毁。那我们通过for循环的时候每次开辟的空间是否都是同一块空间呢?哈哈,我们同样可以来测试一下:

但是我们也可以测试一下,当我们再次运行该程序的时候地址就已经产生了变化,不信你试试。

我们再来看看第二个程序:static修饰局部变量的时候,i变量在运行的过程中出了函数并没有被释放,更改了临时变量的声明周期,因此i才会不断累加。我们先来认识一下C程序的地址空间:

局部变量被static修饰的时候开辟的空间位置变化,存储位置发生了变化,开辟到了静态区里面。因此生命周期变为了整个工程

到了这里只是一个最基础的部分啦,后续小生会不断更新更多的知识,你现在可以回答之前的那几个问题了吗?哈哈哈,大神们,如果觉得有所帮助别忘了给小生三连哦,你们的鼓励就是我最大的动力.

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-b4BftwhE-1712937482015)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2401_84264536/article/details/137698793

智能推荐

1-8 linux系统中的软件管理-程序员宅基地

文章浏览阅读99次。#### 1.Linux中软件包的类型 ####1.DEB#UBlinux DEBlinux2.RPM #redhat centOS fadora3.bz2|gz|xz#1.需要源码安装需要编译 #2.绿色软件,直接可用 #ntfs-3g_ntfsprogs-2017.3.23.tgz需要编译 "configur...

基于动态用户偏好和服务质量的推荐算法-程序员宅基地

文章浏览阅读4.9k次。引用:Zhang Y, Qian Y, Wang Y. A RecommendationAlgorithm Based on Dynamic User Preference and Service Quality[C]//2018 IEEEInternational Conference on Web Services (ICWS). IEEE, 2018: 91-98.摘要:在服务计算领域...

python二级考试选择题公共基础知识_计算机二级选择题(公共基础知识)-程序员宅基地

文章浏览阅读1.9k次。在这一期的文章主要以计算机二级选择题的公共基础知识进行讲解。在计算机二级考试当中,选择题中的二级公共基础知识是必考的部分。很多考生对计算机二级的公共基础知识选择题有很多不解。二级公共基础知识选择题主要考这些内容。未来教育题库界面截图主要由四章内容组成:数据库结构与算法、程序设计基础、软件工程基础、数据库设计基础一、数据库结构与算法这一章主要难点是对栈与队列以及树与二叉树的理解。话不多说,,直接上例..._计算机二级python公共基础题选择题是什么

VS2013 修改TFS的本地映射路径-程序员宅基地

文章浏览阅读2.2k次。在源代码管理器里面 找到你的本地工作区然后点击编辑按钮修改本地目录_vs怎么更改映射路径

【BZOJ】3224: Tyvj 1728 普通平衡树-程序员宅基地

文章浏览阅读77次。【题意】1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数)【算法】平衡树(treap)重要的细节以注释的形式标注在代码中。#include<cstdio>...

视图中的键保留表_视图键保留表-程序员宅基地

文章浏览阅读3.2k次。视图中的键保留表:连接视图中所有更新的列必须映射到键保留表的列中,也就是视图DML操作的列必须映射到键保留表的列中键保留表的理解是:一个复杂视图,若需要出现键保留表的话则必须保证基表中至少有一张表是有主键的! 其次,这两张表在进行关联时(可以是表连接也可以是多表查询,但一定要有关联条件,其关联条件其实相当于两表的主外键关系),如果关联条件是使用了主键的话,则外键表为键保留表_视图键保留表

随便推点

小米组织架构再调整,王川调职,雷军自任中国区总裁_小米更换硬件负责人-程序员宅基地

文章浏览阅读335次。5月17日,小米集团再发组织架构调整及任命通知。新通知主要内容为前小米中国区负责人王川调职,雷军自任中国区总裁。小米频繁调整背后,雷军有些着急了中国区手机业务持续下滑。根据IDC最近公布的数据,小米一季度全球出货量为2750万台,相比去年同期的2780万台,小幅下降。参考Canalys、Counterpoint的统计,小米一季度出货量也都录得1%的同比下滑。作为对比,IDC数据显示,华为同期出..._小米更换硬件负责人

JAVA基础学习大全(笔记)_java学习笔记word-程序员宅基地

文章浏览阅读9.1w次。JAVASE和JAVAEE的区别JDK的安装路径[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-perPRPgq-1608641067105)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201222001641906.png)]卸载和安装JDK[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SYnXvbAn-1608641067107)(C:\Users_java学习笔记word

vue-echarts饼图/柱状图点击事件_echarts 饼图点击事件-程序员宅基地

文章浏览阅读7.8k次,点赞2次,收藏17次。在实际的项目开发中,我们通常会用到Echarts来对数据进行展示,有时候需要用到Echarts的点击事件,增加系统的交互性,一般是点击Echarts图像的具体项来跳转路由并携带参数,当然也可以根据具体需求来做其他的业务逻辑。下面就Echarts图表的点击事件进行实现,文章省略了Echarts图的html代码,构建过程,option,适用的表格有饼图、柱状图、折线图。如果在实现过程中,遇到困难或者有说明好的建议,欢迎留言提问。_echarts 饼图点击事件

操作系统思维导图(一)_操作系统课程思维导图-程序员宅基地

文章浏览阅读1.3k次,点赞4次,收藏14次。内容整理自,华中科技大学,苏曙光老师《操作系统原理》,可在MOOC课程学习相关课程。_操作系统课程思维导图

vite build-程序员宅基地

文章浏览阅读4.3k次。vite在开发阶段采用的是按需加载的方式,不会将所有文件打包。但是生产环境的部署是需要进行打包的,这里它使用的是rollup打包方式。对于代码切割的需求,使用原生动态导入,因此打包后支持新浏览器,对IE的兼容性不是很好,但是可以用对应的polyfill解决。使用esbuild来处理需要pre-undle的在cli.ts的build命令中引入build.ts调用doBuild方法,在这个方法中配置打包参数(input output plugin等)调用buildHtmlPlugin解析文件入口in_vite build

Scala:访问修饰符、运算符和循环_scala ===运算符-程序员宅基地

文章浏览阅读1.4k次。http://blog.csdn.net/pipisorry/article/details/52902234Scala 访问修饰符Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。如果没有指定访问修饰符符,默认情况下,Scala对象的访问级别都是 public。Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层_scala ===运算符

推荐文章

热门文章

相关标签