C:关于static 和 extern 关键字的介绍-学习笔记

目录

1、作用域与生命周期

1.1 作用域

1.2 生命周期

1.3 变量的作用域和生命周期之间的关系

2、static 和 extern

2.1 static 修饰局部变量:

2.2  static 修饰全局变量(包含extern的作用):

2.3 static修饰函数:

结语:


本篇文章将介绍两个关键字 static 、extern的作用


1、作用域与生命周期

在介绍 static 和 extern之前,我们需要先了解:作用域与生命周期

1.1 作用域

作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效(可用)的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

  1.  局部变量的作用域是变量所在的局部范围。
  2. 全局变量的作用域是整个工程(项目)。

该怎么理解呢?举个例子

int main()
{{int a = 10;printf("a1 = %d\n", a);}// printf("a2 = %d\n", a); return 0;
}

a1可以打印,a2不可以打印

从上图我们可以看到a2显示是未声明的标识符,是因为a2并不在int a = 10 所在的大括号内。

a只能在局部范围内使用。所以a的作用域就是大括号范围。

因此我们可以知道局部变量的作用域就是变量所在的局部范围。

那全局变量的作用域我们也就可以推算出来,全部变量的作用域是整个工程。

int a = 10;//全局变量
void test()//子函数
{printf("a3 = %d\n", a);
}
int main()//主函数
{{printf("a1 = %d\n", a);}printf("a2 = %d\n", a); return 0;
}

不管a在哪里,只要在该工程内,都是可以使用的,所以全局变量的作用域是整个工程。

1.2 生命周期

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

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

这个该怎么理解呢?

首先是关于局部变量生命周期的理解:

int main()
{{int a = 10;printf("a1 = %d\n", a);}// printf("a2 = %d\n", a); return 0;
}

图解: 

从上图我们可以看到,当a出了大括号范围后,a就不能使用了

所以,当a创建的时候,生命周期开始,当a出作用域后就没法用了,所以被销毁,也就是生命周期结束。

所以局部变量的生命周期是:进入作用域变量创建,生命周期开始,出作用域生命周期结束

所以我们也可以认为全局变量的生命周期就是整个程序的生命周期。

1.3 变量的作用域和生命周期之间的关系

变量的作用域和生命周期密切相关,但又有所不同。

作用域决定了变量在程序中的哪些部分可以被访问和操作,而生命周期则决定了变量存在和有效的时间段。

一般来说,变量的作用域会影响其生命周期。

当一个变量具有局部作用域(例如在函数内部定义的非静态变量)时,它的生命周期通常与函数的执行相关。函数被调用时变量被创建,函数执行结束后变量被销毁,其生命周期相对较短。

而具有全局作用域的变量,或者在函数内部使用 static 关键字修饰的变量,其作用域通常更广,生命周期也更长,从程序开始运行一直到程序结束。

例如:

void fun() 
{int a = 10;  // 局部变量,作用域在 fun 函数内,生命周期随函数执行开始和结束
}int b = 20;  // 全局变量,作用域整个程序,生命周期整个程序

在上述示例中,a 的作用域仅限于 fun 函数,其生命周期也在函数执行期间。而 b 的作用域是整个程序,生命周期也是从程序启动到程序结束。

作用域限定了变量能被使用的范围,而生命周期决定了变量存在的时间跨度,作用域在一定程度上会反映和影响变量的生命周期。

2、static 和 extern

static 和 extern 都是C语⾔中的关键字。

static 是静态的的意思,可以用来:

  • 修饰局部变量
  • 修饰全局变量
  • 修饰函数

extern 是用来声明外部符号的。

2.1 static 修饰局部变量:

代码1:不含static 

void test()
{int a = 5;a++;printf("%d ", a);
}
int main()
{int i = 0;for (i = 0; i < 6; i++){test();}return 0;
}

该代码的结果会是多少呢?来一起看一下

欸,6个6,怎么得到的呢?

在上述代码中,test 函数内部定义的变量 a 是一个局部变量。

每次调用 test 函数时,都会为 a 分配新的内存空间,并初始化为 5 。然后 a 自增并打印其值。

在  main 函数的  for循环中,连续调用了 6 次 test 函数。

由于每次调用都是独立的,a 的值都会重新从  5 开始计算,然后自增到 6 并打印。

所以会连续打印出 6个6 。

代码2:含static 

void test()
{static int a = 5;//加上statica++;printf("%d ", a);
}
int main()
{int i = 0;for (i = 0; i < 6; i++){test();}return 0;
}

该代码的结果又会是什么呢?

现在的结果变为了6 7 8 9 10 11。为什么呢?

好像这里每一次调用函数后a产生的值没有被刷新,当下一次调用的时候,会继续使用上一次留下来的值。也就是说进来的a不会再重新创建。

为什么呢?我们可以通过对比来理解static的作用

代码1的test函数中的局部变量i是每次进入test函数先创建变量(生命周期开始)并赋值为0,然后 ++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)。

代码2中,我们从输出结果来看,i的值有累加的效果,其实test函数中的i创建好后,出函数的时候是 不会销毁的,重新进⼊函数也就不会重新创建变量,直接上次累积的数值继续计算。

我们知道内存被划分为栈区,堆区,和静态区

分别存放的东西:

栈区:局部变量、形式参数

堆区:动态内存分配,malloc,calloc,realloc等函数

静态区:全局变量,静态变量

结论:static修饰局部变量改变了变量的生命周期,生命周期改变的本质是改变了变量的存储类型,本来⼀个局部变量是存储在内存的栈区的,但是被 static 修饰后存储到了静态区。存储在静态区的变量和全局变量是一样的,生命周期就和程序的生命周期⼀样了,只有程序结束,变量才销毁,内存才回收。但是作用域不变的。

也就是说被static修饰的局部变量会增长生命周期,即使出了作用域,也不会被销毁

当a被声明为static时,它具有以下特点:

  1. 只会被初始化一次。
  2. 在函数调用之间,其值会被保留。

注意:static修饰的变量是可以被改变的。

2.2  static 修饰全局变量(包含extern的作用):

首先,我们现在add.c文件定义一个全局变量int g_val = 2024;

然后再xu.c中使用全局变量intg_val

结果展示:

哎,为什么打印不出来呢?

这时候我们需要给代码做一点小小的改变,我们再int main()上面加上一行代码

extern int g_val; 这时候我们再来看一下

没有报错,成功打印了。

从上面对比你知道extern的作用了吗?

extern 是用来声明外部符号的,如果⼀个全局的符号在A文件中定义的,在B文件中想使用,就可以使用extern进行声明,然后使用。

如果我们用static来修饰全局变量会产生什么影响呢?来看一下

我们可以发现,原来可以运行的程序由于用static修饰int g_val无法运行了,这是为什么呢?

这就是static修饰全局变量的作用:

使用static修饰全局变量,会使得被static修饰的全局变量只能在本源文件内使用,不能在其他源文件内使用。

结论:

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

所谓的外部链接属性,就是可以跨文件使用。

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

2.3 static修饰函数:

static修饰函数与修饰全局变量非常相似。

当使用extern声明add(int x, int y)后,图中函数add(int x, int y)能否使用呢?

肯定是可以的,但是,当我们使用static修饰函数add(int x, int y)后,程序是否还能运行成功吗?

不能正常运行。所以static修饰函数后,函数也就不能跨文件使用了。

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


结语:

本篇文章将告一段落,这篇文章主要讲了两个关键字static 和 extern的作用以及用法

同时还介绍了两个名词作用域与生命周期,在介绍static的用法中,使用了将代码放在多个文件的用法,明天会更新将代码拆分放在多个文件的操作,期待大家的到来!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

由浅入深的了解进程(5)--环境变量

环境变量 前言环境变量1、更多的环境变量及添加和删除2、整体理解环境变量系统 3、内建命令 前言 在上一篇文章中简单的介绍了环境变量&#xff0c;但是没有讲述的比较全面了&#xff0c;所以现在再写一篇来介绍环境变量。 环境变量 在上一篇文章中&#xff0c;我们已经简单…

机械学习—零基础学习日志(高数18——无穷小与无穷大)

零基础为了学人工智能&#xff0c;真的开始复习高数 学习速度加快&#xff01; 无穷小定义 这里可以记住&#xff0c;无穷小有一个特殊&#xff0c;那就是零。 零是最高阶的无穷小&#xff0c;且零是唯一一个常数无穷小。 张宇老师还是使用了超实数概念来讲解无穷小。其实是…

Mecanim Animation System

动画系统简介 Unity 有一个非常丰富而又复杂的动画系统&#xff0c;官方称其为Mecanim。该系统具有以下功能&#xff1a; 支持从外部导入动画剪辑&#xff0c;如&#xff1a;fbx、mb | ma&#xff08;Autodesk maya 原件&#xff09;、.max&#xff08;3ds Max原件&#xff09…

Final Shell for Mac 虚拟机连接工具【简单易操作,轻松上手】【开发所需连接工具】

Mac分享吧 文章目录 效果一、下载软件二、安装软件三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件 链接&#xff1a;http://www.macfxb.cn 二、安装软件 三、运行测试 安装完成&#xff01;&#xff01;&#xff01;

Redis学习[6] ——Redis缓存设计

八、Redis缓存设计 8.1 为什么Redis用作缓存&#xff1f; 一般来说&#xff0c;数据库的数据都是落在磁盘上的&#xff0c;会导致读写速度很慢。如果用户的请求量非常大&#xff0c;数据库很容易崩溃。由于Redis的数据保存在内存中&#xff0c;读写速度很快&#xff0c;所以R…

React(四):DOCX文件在线预览

效果 注意 ⚠️注意&#xff1a;部分文件预览存在问题 依赖 $ yarn add docx-preview $ yarn add jszip源码 import ./index.scss; import {useRef} from react; import type {UploadRequestOption} from rc-upload/lib/interface; import {Upload, Button, message} from an…

【时时三省】(C语言基础)一维数组

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ——csdn时时三省 数组 数组就是一组数 数组的官方定义是一组相同类型元素的集合 一堆数组的创建和初始化 求组的创建 数组是一组相同类型元素的集合。数组的创建当时是: type&#xff3f;t arr&#x…

【过题记录】8.4(robocom补题,网络流)

今天robocom国赛&#xff0c;因为一个bool函数忘记return 1而裂开(错失21分) 以此为戒 贪心消消乐 其实就是一个求最大子矩阵和的板子题 利用最大子段和的思想 枚举矩阵中的上下界 压成一维后利用最大子段和 O ( n ) O(n) O(n)处理 复杂度 O ( n 3 ∗ k ) O(n^3*k) O(n3∗k) k为…

nginx: [error] open() “/run/nginx.pid“ failed (2: No such file or directory)

今天 准备访问下Nginx服务&#xff0c;但是 启动时出现如下报错&#xff1a;&#xff08;80端口被占用&#xff0c;没有找到nginx.pid文件&#xff09; 解决思路&#xff1a; 1、 查看下排查下nginx服务 #确认下nginx状态 ps -ef|grep nginx systemctl status nginx#查看端口…

[CTF]-PWN:格式化字符串漏洞题综合解析

printf型格式化字符串漏洞&#xff1a; 任意地址写&#xff1a; 32位&#xff1a; 例题&#xff08;inndy_echo&#xff09;&#xff1a; 有格式化字符串漏洞&#xff0c;可以修改printf的got表内地址为system&#xff0c;传参getshell 解法一&#xff1a; 在32位中可以使…

vscode的json文件解析

vscode的json文件解析 0.参考链接1.什么是JSON2.JSON语法2.0数据类型2.1对象2.2数组2.3嵌套 3.vscode包含的JSON文件介绍4.vscode包含的JSON文件解析4.1 task.json4.2 launch.json4.3 settings.json4.4 c_cpp_properties.json4.5 package.json&#xff08;详细的看参考链接&…

Python设计模式 - 抽象工厂模式

定义 抽象工厂模式是一种创建型设计模式&#xff0c;它提供了一种创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。 产品等级结构与产品族 为了更好地理解抽象工厂模式&#xff0c;先引入两个概念&#xff1a; 产品等级结构&#xff1a;就是产品的…

试用AWS全新神器:Amazon Bedrock的「Open Artifacts」版Claude.ai Artifacts

Claude.ai的Artifacts真是太方便了。 GitHub上的AWS Samples仓库中有一个仿制Artifacts的应用程序。 Open Artifacts for Amazon Bedrock https://github.com/aws-samples/open_artifacts_for_bedrockhttps://github.com/aws-samples/open_artifacts_for_bedrock本文将介绍「…

【C++】数组案例 五只小猪称体重

题目&#xff1a;给出五只小猪体重&#xff0c;找出最大的体重的值并打印 思路&#xff1a;利用数组写入五只小猪的体重&#xff0c;让每一个元素都赋值给一个整型变量并每赋值一次就于下一个数组中的元素比&#xff0c;若是大就继续赋值给这个变量&#xff0c;若是小则不赋值…

H81002S 1.7mm网络变压器:BMS汽车蓝牙接收器中的超薄共模电感科技

华强盛导读&#xff1a;在当今这个日新月异的汽车科技领域&#xff0c;每一处细节都蕴含着创新与突破。作为电动汽车心脏的电池管理系统&#xff08;BMS&#xff09;&#xff0c;其高效稳定的运行不仅关乎续航与安全&#xff0c;更是智能化驾驶体验的基石。而在这背后&#xff…

win7安装mysql-installer-community-8.0.11.0

1、安装Microsoft Visual C 2019 Redistributable Package (x64) 官网下载地址&#xff1a;https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?viewmsvc-160#latest-microsoft-visual-c-redistributable-version 通过百度网盘分享的文件&#xff1…

Ubuntu安装nvidia-docker并使用的正确方式

Ubuntu安装docker: ubuntu(24.04)以及WSL2安装docker的详细教程_unbantu安装docker-CSDN博客文章浏览阅读646次,点赞5次,收藏3次。默认情况下,只有root用户和docker组的用户才能运行Docker命令。我们可以将当前用户添加到docker组,以避免每次使用Docker时都需要使用sudo。…

DAP-Seq:解锁转录因子结合位点的新钥匙

引言&#xff1a; 在基因组学的浩瀚宇宙中&#xff0c;转录因子如同掌管基因表达的神秘钥匙。它们与DNA上的特定序列结合&#xff0c;调控着生命活动的每一个节拍。然而&#xff0c;传统的研究方法在探索这些结合位点时面临诸多挑战。今天&#xff0c;我们将一起了解一种创新技…

多路I/O复用之select、poll、epoll

一、多进程/多线程模型的不足 为每个请求分配一个进程或线程的方式会带来较大的资源开销。创建和切换进程/线程需要消耗系统资源&#xff0c;包括内存、CPU 时间等。例如&#xff0c;在一个大规模的服务器环境中&#xff0c;如果同时有数千个请求到来&#xff0c;为每个请求创建…

01 LVS负载均衡群集

集群 在互联网应用中&#xff0c;随着站点对硬件的性能、响应速度、服务稳定性、数据可靠性等要求越来越高&#xff0c;单台服务器越来越力不从心 集群的含义 Cluster&#xff0c;集群也叫群集由多台主机构成&#xff0c;但对外只表现为一个整体 集群分类 类型 负载均衡集…