【C语言深度解剖——第二节(关键字2)】《C语言深度解剖》+蛋哥分析+个人理解

2024-01-06 03:28

本文主要是介绍【C语言深度解剖——第二节(关键字2)】《C语言深度解剖》+蛋哥分析+个人理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今日的星辰辉映太古的源起,过往的故事指引明日的生死!(王者荣耀李信)
本文由@睡觉待开机原创,未经允许不得转载。
本内容在csdn网站首发
欢迎各位点赞—评论—收藏
如果存在不足之处请评论留言,共同进步!

这里写目录标题

  • 前言
  • 1.static关键字修饰全局变量和函数
    • 1.1多文件内容介绍
    • 1.2头文件
    • 1.3static函数+全局变量与函数
  • 2.static关键字修饰局部变量
  • 3.static关键字修饰的意义:

前言

本节内容主要是围绕static关键字来展开的,重点阐述了static创建的意义,由来,使用…

1.static关键字修饰全局变量和函数

在介绍static关键字之前,我们首先来准备一下预备知识,同样这些预备知识也是比较关键的。

1.1多文件内容介绍

在同一个vs项目当中,有许多源文件(后缀为.c文件),其中多文件是指的便是多个.c文件(下图)。
在这里插入图片描述
那我来问大家几个问题,看看大家对多文件了解多少:
1.自定义函数是否可以直接被调用?可以!!!
2.全局变量是否可以被直接调用?不可以!!!

在这里插入图片描述
在main文件中,我并没有包含test的头文件但是却可以调用起来,下面来主要解释一下为什么会出现这种情况?
因为报错是在编译阶段完成的,编译器在编译函数阶段没有发现什么特别大的错误。
在我们写完代码的时候,编译器要对我们写的代码要进行编译链接,是分别对每个源文件进行处理的,其中在编译这一整个过程中,我们写的函数是以某种形式存在的,编译器并不会对其进行详细处理,发现找不到这么一个自定义函数时候,编译器顶多报个警告而已,实际上到了链接这个过程编译器才会把两个文件链接起来,发现在另一个文件中找到了这么一个函数定义,也就运行成功了。

在这里插入图片描述
但是我们的定义的全局变量在编译阶段就会被编译器辨认出没有定义,自然也就编译器给你终止程序了,也就不会运行起来。

为了解决这个问题,我们C语言中有一个专门用来声明的关键字:extern关键字
只要我们在我们需要声明的文件中extern一下这个变量或者函数,编译器便可以在编译期间就可以知道有这么个变量允许调用,也就不会报错了。

但是这里我需要强调一个细节,是这样的,有很多初学者会把声明写成这个样子:

extern int n = 100;

这种写法对吗?显然是错误的,至于为什么,这牵扯到了变量的声明的本质理解。
声明并没有开辟空间,但是赋值操作需要空间存放值。
在C语言深度解剖第一节内容我们说过,变量定义本质上是开辟空间,变量声明本质上是告知,两者最大的差距在于有没有空间被创建出来,extern是声明的关键字,但是在上面的写法中却要给n赋值,既然要赋值就得需要空间啊,但是声明是没有开辟空间的!

看下面图片,声明之后没有任何报错甚至是警告也没有:
在这里插入图片描述
但是有个问题哈,就是我们在做一个项目的时候,往往都会有几十个甚至是几百个这样的源文件,我们难道是每个源文件在调用其他文件的变量或者函数的时候都需要extern声明吗?这样做的很大问题就是,维护成本太高了!

1.2头文件

为了解决这个问题,C语言中有专门的文件来存放声明内容,这个文件称为:头文件(后缀为.h)

在这里插入图片描述

头文件有一个比较普遍的问题就是重复问题,重复包含头文件也就是多重复了几次,也不会报错其实,但是会重复拷贝头文件内容,造成效率降低。
下面给出一个解决方法:在头文件中包含#pragma once

头文件中的内容应该写什么?库头文件,自定义函数的声明,变量声明,宏定义等等…

注意:
1.(库文件一半用<库文件名称>这个符号来进行声明,自定义源文件名称用“源文件名称”双引号来进行声明) 约定俗成而已。
2.函数声明与变量声明都建议带上extern,虽然说函数声明可以不用带extern,毕竟不写声明都可以允许,同时函数声明与定义要保持一致。

有了上面的知识进行铺垫,下面来介绍static关键字哈。

1.3static函数+全局变量与函数

直接给结论:
static+全局变量(函数):static的全局变量只可以在本文件中使用,不再允许直接被引用到其他文件当中,改变的变量(函数)的作用域。但是这里需要注意的是static修饰的变量或者函数可以被间接访问

在这里插入图片描述
被static修饰的局部变量和函数虽然不可以被直接访问,但是可以被间接进行访问:(函数嵌套)
在这里插入图片描述

2.static关键字修饰局部变量

static关键字修饰局部变量,会改变局部变量的生命周期,让临时的生命周期延长为类似于全局变量的生命周期。
临时变量(局部变量)的生命周期大家可以看下面代码来进行体会一下:

//体会临时变量的生命周期
void my_print(void)
{int a = 1;printf("%d\n", a);a++;
}
int main()
{int i = 0;for (i = 0; i < 10; i++){printf("it is the %d time:\n", i);my_print();}return 0;
}

在这里插入图片描述
这其实就是因为每次循环进入自定义函数的时候都是重新创建和销毁临时变量a,所以a的值始终是1…
但是,如果我给a加一个static进行修饰:
在这里插入图片描述

3.static关键字修饰的意义:

至于为什么C语言要造static关键字,其实我认为可以这样理解:
C程序是面向程序员的,最终是要造出一个比较大的项目来进行应用的,那这个比较大的项目就会涉及到很多的源文件,这就涉及到多文件,头文件等等,那么C程序运行时候,一定会进行一个数据交互,为了减少维护的成本,那么C设计者一定会允许变量函数跨文件进行访问,那么就再次验证的头文件的重要性,但是我想说如果所有文件都是互关的,那么对应的一些功能接口就会很多,那么意味着程序的暴露程度就会越高,那么代码的隐秘性就会越差,不利于代码的安全性;还有一点就是接口太多,用户的使用成本会比较高,为了解决上面说的两个问题,static关键字这种让变量程序文件隐藏起来的关键字应运而生。

这篇关于【C语言深度解剖——第二节(关键字2)】《C语言深度解剖》+蛋哥分析+个人理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/575074

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程