【C语言】详解static和extern关键字

文章目录

  • 1. 前言
  • 2. 作用域和生命周期
    • 2.1 作用域
      • 2.1.1 全局变量和局部变量
    • 2.2 生命周期
  • 3. static关键字
    • 3.1 static修饰的局部变量
  • 4. extern关键字
  • 5. extern和static关键字的相互作用
    • 5.1 static修饰函数
  • 6.总结

1. 前言

可能在你遇到这篇文章之前,你可能并未听过C语言中还有staticextern这两个关键字。或者你也许听过但是并未使用过。
这些都不是问题,在本文中,我将细细的给大家揭晓这两个关键字背后的秘密,及以后我们该如何使用它们。🥇🥇😊

2. 作用域和生命周期

再讲staticextern这两个关键字之前,有必要先给大家讲一下变量的作用域和生命周期。

2.1 作用域

作用域是个什么东东?
顾名思义,作用域就是变量能够作用的范围。换句话说,就是变量能够在这个范围内生效,出了这个范围之后,变量就不起作用了。

这就又引发出一个问题:这个所谓的"范围"在代码中如何界定?
界定的方法:是以一个 {} 为 标志,每一个{}就代表着一个作用域。

听到这里,你可能还是一头雾水。下面我就给几个例子,让你感受到作用域带来的魅力!
1
我们稍微再修改一下(就是在变量a后面加一个花括号并在里面写一点内容):
2

3

那如果我们在图示花括号后面,要打印一个变量b的值,程序还能正确运行吗?

4
可以看到,编译器给我们报的错误:“b”未声明的标识符。这也就说明了,这个范围已经超出了变量b的作用域了,因此编译器才无法识别出变量b。

通过上述的例子,我相信大家已经对作用域的概念已经深刻的理解了。

2.1.1 全局变量和局部变量

既然都讲到了作用域,那就必须得聊一下全局变量和局部变量了。
变量按照作用域进行分类,可以分为全局变量和局部变量。

全局变量:拥有整个项目工程的作用域。换句话说,就是它能够在整个代码文件中都有效。全局变量是存储在内存的静态区
局部变量:拥有在该范围内的作用域,出了这个范围该变量就失去作用了。局部变量是存储在内存的栈区的

注意:全局变量应尽量少地在编程的过程中使用。因为,全局变量所带来地不可控的因素太多了,比较容易错误的使用。

全局变量和局部变量
那我们该如何在代码中,识别出哪个变量是全局变量还是局部变量呢?

很简单,仔细观察上面的代码,可以看到,全局变量是写在main函数外部的。
所以,我们可以由此得到一个结论:全局变量是出现在main函数的外部的,局部变量是出现在函数内部(包括自定义函数、库函数等)的变量

另外,再向大家声明一个点:
在我们初步学习变量的命名规则时,里面规定:变量的命名是不能重复的。这里我拓展一个点就是,此条件是在同一个作用域下才生效。
可能有的读者已经get到我的点了。

你不是说这个条件是在同一个作用域下才生效的麻,也就说明了在不同作用域下我可以使用相同的变量名。

那么,如果我全局变量和局部变量都用同一个变量名时,编译器又该如何接招呢
答案是:局部变量优先。换句话说,在局部变量所处的作用域中,用该局部变量的值,而不是全局变量。

下面我就写一段代码,验证我们的猜想:

#include<stdio.h>
int a = 88;

int main()
{
	int a = 66;
	printf("%d\n", a); //打印a的值为66
	return 0;
}

结果是:
结果
可以看到,打印出来的值是66,而不是88。这就正是验证了我们的猜想是正确的。

2.2 生命周期

所谓的生命周期就更容易理解了,它就是:

⽣命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的⼀个时间段。

  1. 局部变量的⽣命周期是:进⼊作⽤域变量创建,⽣命周期开始,出作⽤域⽣命周期结束。
  2. 全局变量的⽣命周期是:整个程序的⽣命周期。

3. static关键字

static关键字修饰的变量我们称它为静态变量

static关键字的作用:改变变量的生命周期,使之拥有全局变量的生命周期。(但是注意一点,这样的操作并未改变变量的作用域)

那我们说的到底对不对,下面我就写代码,来探讨一下这个问题:

3.1 static修饰的局部变量

例子
可以看到,含有static修饰变量似乎有种记忆能力,它给我们的一种感觉就是能够在之前操作的结果基础上继续进行操作。

对⽐代码1和代码2的效果,你就能理解 static 修饰局部变量的意义。

  • 代码1的test函数中的局部变量i是每次进⼊test函数先创建变量(⽣命周期开始)并赋值为0,然后
    ++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)。
  • 代码2中,我们从输出结果来看,i的值有累加的效果,其实 test函数中的i创建好后,出函数的时候是
    不会销毁的,重新进⼊函数也就不会重新创建变量,直接上次累积的数值继续计算。

使用建议:未来⼀个变量出了函数后,我们还想保留值,等下次进⼊函数继续使⽤,就可以使⽤static
修饰。

4. extern关键字

extern关键字的作用:赋予变量外部链接属性。

什么是外部链接?
这个问题通常会出现在这么一个场景中,就是我们在大型程序编写中,我们都会将程序的代码划分为多个.c文件,这样做的目的不仅可以增加代码的可读性,还可以提高团队的编程效率。那我们现在假设有个A文件和B文件,A文件的内容和B文件的内容是不能相互使用(相信这个点,大家在编程时都知道),如果强行使用,编译器就会报出错误。

那么现在我接受到了一个任务:我必须要在文件B中使用文件A的内容(一些变量的值、函数等等)。

那我们该怎么做?
用extern关键字。

在展示代码之前,想跟大家聊一聊,为什么就是用这个关键字?
对于文件A来说,文件B是属于外部文件。那么对于文件B来说,文件A里面的内容就属于外部内容。试想一下,两个毫不相干的东西想要相互使用双方的内容,那就必须得建立一个桥梁(链接)。而这个桥梁能够让文件A能够使用文件B的内容,建立桥梁的操作就是在建立外部链接属性。extern在这方面就是专业对口的。

在下面就举个例子:

首先在用这个关键字时,至少得创建两个或两个以上的.c文件。在本例中,创建两个.c文件。

在test1.c的内容:

int a = 66;

在test.c的内容:

#include<stdio.h>
extern int a;//这里的变量名必须与test1.c中你想引用的变量名得是一致的
int main()
{
	printf("a = %d\n", a);
	return 0;
}

extern关键字

5. extern和static关键字的相互作用

上面的例子如果你看懂的话,那就太好了。我们继续突发奇想地改造上述的代码。

我们这样改造:
将test1.c中的变量变为静态变量

static int a = 66;

再编译会出现什么情况?
例子
😲😲😲既然改了一下代码就报错了,这是什么原因呢?
就是static和extern关键字相互作用的结果。

结论:⼀个全局变量被static修饰,使得这个全局变量只能在本源⽂件内使⽤,不能在其他源⽂件内使⽤。
本质原因是全局变量默认是具有外部链接属性的,在外部的⽂件中想使⽤,只要适当的声明就可以使
⽤;但是全局变量被 static 修饰之后,外部链接属性就变成了内部链接属性,只能在⾃⼰所在的源
⽂件内部使⽤了,其他源⽂件,即使声明了,也是⽆法正常使⽤的。

使⽤建议:如果⼀个全局变量,只想在所在的源⽂件内部使⽤,不想被其他⽂件发现,就可以使⽤
static修饰。

5.1 static修饰函数

相信初学C语言的读者们可能都没有看过这种写法,static竟然还能修饰函数。

情况一:
在test1.c中的内容:

int Add(int x, int y)
{
	return x + y;
}

在test.c中的内容:

#include<sdtio.h>
extern int Add(int x, int y);
int main()
{
	printf("%d\n",Add(2,3));
	return 0;
}

1
注意,在Add函数形参这部分,可以不用专门写x和y,只写类型也可以。
2

情况二:

在test1.c内容中:

static int Add(int x, int y)
{
	return x + y;
}

在test.c内容中:

#include<sdtio.h>
extern int Add(int x, int y);
int main()
{
	printf("%d\n",Add(2,3));
	return 0;
}

再看看和之前的代码有什么不同?
编译
发现代码直接报错了。

解释:
其实 static 修饰函数和 static 修饰全局变量是⼀模⼀样的,⼀个函数在整个工程都可以使用,
被static修饰后,只能在本⽂件内部使用,其他文件无法正常的链接使用了。

本质是因为函数默认是具有外部链接属性,具有外部链接属性,使得函数在整个工程中只要适当的声
明就可以被使用。但是被 static 修饰后变成了内部链接属性,使得函数只能在自己所在源文件内部
使用。

使⽤建议:⼀个函数只想在所在的源⽂件内部使⽤,不想被其他源⽂件使⽤,就可以使⽤ static 修
饰。

6.总结

在本文中,介绍了变量的作用域和生命周期,还说明了static和extern两个关键字以及它们如何使用。
希望能帮到大家。

文章创作不易,如果你觉得写得好不错的话,请不要吝啬你们的点赞和收藏哦!!!🙏🙏🙏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/687586.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA2023.1.4配置springboot项目

新建“Spring Initializr”项目 勾选以下三个依赖项即可。 springboot分为代码层、资源层和测试层。 代码层 根目录&#xff1a;src/main/java 入口启动类及程序的开发目录。在这个目录下进行业务开发、创建实体层、控制器层、数据连接层等。 资源层 根目录&#xff1a;src…

奇迹MU最强法师介绍

1、黑龙波 释放出深渊中的黑龙之魂&#xff0c;对一定范围内的目标造成中等程度伤害。 奥义&#xff1a; 怒哮——法师释放出深渊龙魂的怨怒之力&#xff0c;在电闪雷鸣中中咆哮的龙魂将对敌人额外造成少量伤害。 魂阵——法师利用法阵控制黑龙之魂进行更大范围的攻击&…

史上最强 AI 翻译诞生了!拳打谷歌,脚踢 DeepL

CoT 推理范式 默认情况下&#xff0c;大语言模型通常是直接给出问题的最终答案&#xff0c;中间推理过程是隐含的、不透明的&#xff0c;无法发挥出大模型最极致的理解能力。如果你用它来充当翻译&#xff0c;可能效果和传统的机器翻译也差不了太多。 如果我们给大模型设计一…

天行健咨询 | 谢宁DOE培训的课程内容有哪些?

谢宁DOE培训的课程内容丰富而深入&#xff0c;旨在帮助学员掌握谢宁问题解决方法在质量管理中的重要作用&#xff0c;并学会如何运用这一方法工具&#xff0c;在不中断生产过程的前提下&#xff0c;找出并解决生产中遇到的复杂而顽固的问题。 首先&#xff0c;课程会详细介绍谢…

SpringCloud Hystrix服务熔断实例总结

SpringCloud Hystrix断路器-服务熔断与降级和HystrixDashboard SpringCloud Hystrix服务降级实例总结 本文采用版本为Hoxton.SR1系列&#xff0c;SpringBoot为2.2.2.RELEASE <dependency><groupId>org.springframework.cloud</groupId><artifactId>s…

Kafka之Producer原理

1. 生产者发送消息源码分析 public class SimpleProducer {public static void main(String[] args) {Properties prosnew Properties();pros.put("bootstrap.servers","192.168.8.144:9092,192.168.8.145:9092,192.168.8.146:9092"); // pros.pu…

【必会面试题】ThreadLocal的底层原理及其使用场景

目录 原理应用场景优势1. 避免线程安全问题2. 提高性能3. 简化代码 注意事项权衡决策 ThreadLocal是Java中用于创建线程局部变量的一个类&#xff0c;它提供了一种将变量绑定到当前线程的技术&#xff0c;使得每个线程都拥有该变量的独立副本&#xff0c;即使是在多线程环境下也…

GitHub生成SSH密钥,使用SSH进行连接

目录 一、生成新的SSH密钥 二、添加新的SSH密钥 三、测试SSH连接 四、SSH密钥密码 五、创建新仓库并推送到github 说明 使用 SSH URL 将 git clone、git fetch、git pull 或 git push 执行到远程存储库时&#xff0c; 须在计算机上生成 SSH 密钥对&#xff0c;并将公钥添加到…

keil program algorithm 出错

前段时间 在 调试下载算法时&#xff0c;遇到一个奇怪的问题 就是 加载下载算法后&#xff0c; 下载算法的RAM空间 大小不能修改为 单片机的最大RAM&#xff0c;只能改到最大4KB的空间大小, 再大就报错 刚开始报错 一直不知道原因&#xff0c;走了很多弯路&#xff0c; 到最…

SharePoint:智能内容管理,释放数据价值

在Microsoft 365的庞大生态系统中&#xff0c;SharePoint常常被忽视&#xff0c;但它却是整个平台的核心。SharePoint不仅承载着OneDrive、Teams、Power Platform等所有Microsoft 365产品的内容存储&#xff0c;更是企业协作和内容管理的基石。助AI技术的加持&#xff0c;Share…

Microbiome | binning+转录组→首个草鱼肠道基因集目录发布啦

草鱼便宜又好吃 但是你了解草鱼吗&#xff1f; 草鱼的肠道里定殖着成千上万的共生微生物&#xff0c;它们与草鱼共同生存&#xff0c;相互影响。这些微生物在草鱼的新陈代谢、免疫调节等方面发挥着重要作用。 虽然同为经济作物&#xff0c;鱼类的微生态相关研究远远…

U盘未安全退出后提示格式化:原因分析与数据恢复策略

在日常工作和生活中&#xff0c;U盘作为便携式存储设备的代表&#xff0c;因其小巧、方便携带和存储容量大等特点而广受欢迎。然而&#xff0c;不少用户在使用U盘的过程中都遇到过一个令人头疼的问题&#xff1a;U盘在没有安全退出的情况下被直接拔出&#xff0c;再次插入时系统…

[职场] 研究生面试自我介绍_1 #经验分享#知识分享

研究生面试自我介绍 想要进入职场&#xff0c;面试是必不可少的。然而想要面试成功&#xff0c;就需要一个让人印象深刻的自我介绍&#xff0c;好的自我介绍可以让面试官&#xff0c;快速了解自己&#xff0c;快速记住自己。 一、范文1 我是一名硕士研究生&#xff0c;即将毕业…

SOLIDWORKS认证考试的目的

在当今日益发展的工程设计和制造领域&#xff0c;SOLIDWORKS作为一款功能强大的三维CAD设计软件&#xff0c;已经得到了广泛的认可和应用。为了评估和提升用户在使用SOLIDWORKS软件时的专业技能和能力&#xff0c;SOLIDWORKS公司推出了认证考试项目。本文将深入探讨SOLIDWORKS认…

.net 下的身份认证与授权的实现

背景 任何一个系统&#xff0c;都需要对于底层访问的页面和接口进行安全的处理&#xff0c;其中核心就是认证和授权。 另外一个问题就是在实际编程过程中&#xff0c;我们的代码有不同的模式&#xff0c;不同的分层或者在不同的项目之中&#xff0c;如何在不同的地方取得用户…

ACDSee Photo Studio Ultimate v17 解锁版安装教程 (图片编辑器)

前言 ACDSee Photo Studio Ultimate 2024&#xff0c;一款适合各类摄影师和创意人士的综合解决方案&#xff0c;具备了经过省时的本地人工智能 (AI) 强化的全新特性和改进功能&#xff0c;使您能够以最小的投入获得最大的控制&#xff0c;从而更轻松地管理、检索和编辑您的照片…

免费分享一套SpringBoot+Vue校园论坛(微博)系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue校园论坛(微博)系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue校园论坛(微博)系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue校园论坛(微博)系统 Java毕业设计…

Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。

文章目录 前言一、项目初始化搭建1、创建项目&#xff1a;test_models_django2、创建应用app01 二、配置mysql三、创建model实例&#xff0c;自动创建数据库表1、创建对象User类2、执行命令 四、思考问题&#xff08;****&#xff09;1、是否会生成新表呢&#xff08;答案报错&…

数据结构——哈希表、哈希桶

哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较&#xff0c;顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN),搜索的效率取决于搜索过程种元素的比较次…

Java递归删除文件夹

Java可以直接删除文件或者空文件夹&#xff0c;但是当文件夹不为空时&#xff0c;就不能直接删除了&#xff0c;这时候可以使用递归将文件夹直接删除 首先我们假设在D盘创建a文件夹&#xff0c;a中有一个b文件夹&#xff0c;b中有一个c文件夹&#xff0c;c中有三个文本文件&…