【C语言static关键字】

news2024/12/25 9:12:37

C语言static关键字

  • C语言之static
    • 1、什么是static?
    • 2、static的意义
    • 3、C/C++ static的属性
    • 4、static的用法
      • 4.1、static修饰局部变量例程
      • 4.2、static修饰全局变量例程
      • 4.3、static修饰函数例程
    • 5、结束语

C语言之static

前言:
先简单了解下“三大区”,在C/C++程序中:
a、栈区:存放局部变量/形式参数等,具有临时属性的变量
d、堆区:存放动态内存所分配的数据,如malloc、free、realloc等
e、静态区:存放全局变量/static所修饰的静态(局部)变量等
如图所示

在这里插入图片描述

1、什么是static?

概念: 是C语言中很常用的修饰符,它被用来控制变量的存储方式和可见性。

作用
a、static静态变量声明符。
b、static 关键字不仅可以用来修饰变量,还可以用来修饰函数。

注意
a、静态变量的存储方式与全局变量一样,都是静态存储方式。
b、静态变量属于静态存储方式,但是属于静态存储方式的变量却不一定就是静态变量。
c、在使用 static 关键字修饰变量时,我们称此变量为静态变量。
d、在声明它的程序块,子程序块或函数内部有效,值保持不变,在整个程序期间分配存储器空间,编译器默认值0。

2、static的意义

当一个函数内部定义了变量,在程序执行到它的定义处时,编译器会它在栈上分配空间,由局部变量的性质可知,函数在栈上分配的空间在此函数执行结束时会释放掉(生命周期/作用域)。

这时我们对这个变量的操作就多了一些约束: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制,而是整个工程都可以反访问了,特别是局部变量名一致时,优先级局部变量所以容易冲突)。

那么就需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。

3、C/C++ static的属性

静态数据成员要在程序一开始运行时就必须存在。因为函数在程序运行中被调用,所以静态数据成员不能在任何函数内分配空间和初始化。

这样,它的空间分配有三个可能的地方,一是作为类的外部接口的头文件,那里有类声明;二是类定义的内部实现,那里有类的成员函数定义;三是应用程序的main()函数前的全局数据声明和定义处。

静态数据成员要实际地分配空间,故不能在类的声明中定义(只能声明数据成员)。类声明只声明一个类的“尺寸和规格”,并不进行实际的内存分配,所以在类声明中写成定义是错误的。它也不能在头文件中类声明的外部定义,因为那会造成在多个使用该类的源文件中,对其重复定义。
static被引入以告知编译器,将变量存储在程序的静态存储区而非栈上空间,静态
数据成员按定义出现的先后顺序依次初始化,注意静态成员嵌套时,要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。

优势
可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。

小结
静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
非静态成员函数可以任意地访问静态成员函数和静态数据成员;
静态成员函数不能访问非静态成员函数和非静态数据成员;

4、static的用法

语法
static修饰变量 + 类型 + 变量名 + 初始化
如:statuc int a = 1
static修饰函数 + 函数类型 + 函数名(参数)
如:static int add(int x, int y)
说明
static常见用法:
1)修饰局部变量
2)修饰全局变量
3)修饰函数

4.1、static修饰局部变量例程

说明
a、这时的局部变量就是静态的局部变量
b、一个普通的局部变量进入函数创建,出函数销毁,但是被static修饰后,进入函数已经创建好了,出函数时候也不再销毁,多次调用函数时,共享一个变量
c、理解为:生命周期变长了,但是作用域不变,只能在局部范围内使用
d、本质:普通的局部变量是存放在栈区上的,但是被static修饰后,是存放在静态区的,静态区的变量生命周期和全局变量的生命周期一样

/*例程1*/
#include <stdio.h>
//void test()
//{
//	int i = 1;//局部变量
//	//这里的i与main函数中的i意义不同
//	i++;
//	printf("%d\n",i);//2 2 2 2 2
//	//输出一次i,则生命周期结束一次
//}
void test()
{
	static int i = 1;//static修饰局部变量
	//使得这里的i,改变局部变量的属性
	i++;
	printf("%d\n", i);//2 3 4 5 6
}

int main()
{
	int i = 0;
	while (i < 5)
	{
		test();//函数独立
		i = i + 1;
	}
	return 0;
}

4.2、static修饰全局变量例程

说明
a、结合test011.c理解
b、全局变量具备外部链接属性的,这种属性决定了全局变量在多个文件中相互使用
c、全局变量在其他源文件内部均可以使用,但是经过static修饰后,使得其变成内部链接属性,其他源文件就不能链接到这个静态的全局变量了。可理解为:公有变私有

/*例程2*/
#include <stdio.h>

//int g_val = 2023;//定义一个全局变量
//当想使用在同工程下的.c文件的全局变量时,需要用extren声明才可以使用
extern int g_val;
//extern 相当于告诉编译器:g_val变量来自工程下的其他文件
void test()
{
	printf("test( ): %d\n",g_val);
}

int main()
{
	printf("%d\n",g_val);
	test();
	return 0;
}
/*test011.c*/
int g_val = 2023;

//static int g_val = 2023;

//static修饰全局变量的时候,将外部链接属性变成了内部链接属性
// 使得g_val只能在当前.c源文件中使用了,不能在其他.c文件中使用了
// 理解为:改变了全局变量的作用域
//本质:在语法层面进行了限制,并未改变存放的区域

4.3、static修饰函数例程

说明
a、结合test011.c理解
b、static修饰int add(int x, int y)函数,使得函数只能在函数自己所在的源文件中使用,不能在其他源文件中使用
c、函数也是具备外部链接属性的,这种属性决定了函数是可以跨文件使用的
d、static修饰函数是把函数外部链接属性改变为内部链接属性,使得函数只能在当前.c文件中使用
e、本质上:static是将函数的外部链接属性变成了内部链接属性(与修饰全局变量,大相近同)

#include <stdio.h>
//函数的定义
//int Add(int x,int y)
//{
//	return x + y;
//}
//函数的外部定义/引用
//借助extern进行声明来自外部的函数
extern int Add(int x,int y);
int main()
{
	int a = 3;
	int b = 5;
	int c = Add(a,b);//函数的调用
	printf("%d\n",c);//8
	return 0;
}
/*test011.c*/
//static修饰函数
//函数也是具备外部链接属性的
//这种属性决定了函数是可以跨文件使用的
//static修饰函数是把函数外部链接属性改变为内部链接属性
//使得函数只能在当前.c文件中使用
int Add(int x, int y)
{
	return x + y;
}

小结
a、static修饰局部变量时,改变了局部变量的生命周期(本质是改变了变量的存储类型)
b、全局变量在其他源文件内部均可以使用,但是经过static修饰后,使得其变成内部链接属性,其他源文件就不能链接到这个静态的全局变量了。可理解为:公有变私有
c、static修饰函数与修饰全局变量十分类似,因为函数与全局变量都具备外部属性链接的特性。

5、结束语

总体来说;
static是一个非常有用的关键字,能够帮助程序员在编写程序时,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护。
因此,编写程序时应该充分发挥static的作用,并合理地搭配其他语句和特性使用,以便更好地保证程序的正确性、可靠性以及严谨性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据人一直做这四项工作,即使不被BI、AI取代,也躲不过35危机!

先说我的观点&#xff1a;数据分析职业不会被BI软件替代。顺便说一句&#xff0c;数据分析职业也不会被chatgpt取代。 大家首先要搞清楚&#xff1a;取代人的从来不是工具&#xff0c;而是会使用工具的人。 数据分析师工作内容 首先&#xff0c;先让我们来全面拆解一下国内数…

聊聊极限编程与测试启发

这是鼎叔的第六十五篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 欢迎关注本公众号《敏捷测试转型》&#xff0c;星标收藏&#xff0c;大量原创思考文章陆续推出。 继续聊聊著名的敏捷研发框架&#xff1a;极限编程。 极限编程&#xff08;Extreme Prog…

从腾讯、阿里、联想的ESG报告,看数字企业发展的「碳门槛」

从“互联网”到“数字化”&#xff0c;再到“ESG”。数字化不仅帮助企业打开了从传统到现代化的通路&#xff0c;也帮助企业打开了从无序到环保、通往低碳的大门。 作者|斗斗 编辑|皮爷 出品|产业家 一年一度的ESG报告披露正在来临。 腾讯发布2022年ESG&#xff08;即“…

一天掌握latex论文编辑,从标题作者,段落,数学公式,图片,图表,到参考文献全流程

目录 以下是一个基于SCI模板的完整LaTeX论文示例&#xff0c;包含注释说明 1. 创建文档&#xff1a; 2. 标题和作者信息&#xff1a; 3. 段落和文本格式&#xff1a; 4. 列表&#xff1a; 5.图片和表格&#xff1a; 5.1插入图片 5.2 插入表格 5.2.1 示例1 &#xff1a;…

计算机组成原理基础复习题(无答案版)

本套题无答案&#xff0c;整理出来适合大家完成课堂学习后&#xff0c;边翻书边对照题目检索答案&#xff0c;加深印象。 目录 一、选择题 二、填空题 三、简答题 四、设计题 一、选择题 1、完整的计算机系统应包括&#xff08; &#xff09;。 A. 运算器、存储器和控制器…

【C#】医学检验系统(LIS)源码

一、医学检验系统&#xff08;Laboratory Information Management System 简称&#xff1a;LIS&#xff09;LIS是HIS系统的一个重要的组成部分&#xff0c;其主要功能是将检验的实验仪器传出的检验数据经分析后&#xff0c;生成检验报告&#xff0c;通过网络存储在数据库中&…

《操作系统》- 线程与进程

目录 一、进程的概念二、进程的结构和特征2.1 进程的结构2.2 进程的特征 三、线程的概念四、进程和线程比较五、线程的实现方式 一、进程的概念 程序放在磁盘上不叫做进程&#xff0c;只有运行起来之后才叫做进程&#xff0c;进程进程就是进行中的程序&#xff01;一次运行就会…

spring boot security使用jwt认证

前言 在前面的几篇文章中&#xff1a; spring boot security快速使用示例 spring boot security之前后端分离配置 spring boot security自定义认证 spring boot security验证码登录示例 基本对常用的基于cookie和session的认证使用场景都已覆盖。但是session属于有状态认证&am…

GAMES101笔记 Lecture10 Geometry1 (Introduction)

目录 Application for Texture(纹理的应用)Environment Map(环境光贴图)Spherical Environment Map(球形环境光贴图)Cube Map(立方体贴图) Texture can affect shading!(纹理可以作用于着色)How to perturb the normal (in flatland)(如何计算法线如何变化呢&#xff1f;)Displ…

《AutoSar实战》读写DID之三:代码实现

文章目录 前言一、检查生成的接口以及数据类型1. 读DID函数接口生成2. 写DID函数接口生成3. 写NvM接口生成4. RAM数组生成 二、代码编写1. 读DID2. 写DID 总结 前言 本系列主要基于DaVinCi工具链来展开具体DID读写的配置以及最终实现。 DID读写功能实现流程包括如下几点&#…

行走江湖,一最多的行

本篇博客会讲解力扣“2643. 一最多的行”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff1a;从上到下遍历二维数组&#xff0c;统计每一行1的个数。使用ret数组的第一个元素维护1最多的行的下标&#xff0c;第二个元素维护最多的1的个数。若发现某一行的1的个数比…

kettle取昨天时间设置任意时间变量

文章目录 kettle取昨天时间&设置任意时间变量设置系统信息增加常量计算器设置变量 总结 kettle取昨天时间&设置任意时间变量 kettle 版本7.1&#xff0c;如下图所示&#xff1a; 所需要组件&#xff1a;1 获取系统信息; 2 增加常量; 3 计算器; 4设置变量 结果可以用于…

yolov8源码解读(part2: 检测,分割)

本文解读下图框中的detection部分 和 没有画出来的分割部分。 注意每个模块右上角的数字,它代表第几个模块, 现在检测和分割的输入都是15, 18, 21个模块的输出(图中圆圈处)。 在代码解读的时候会用[15,18,21]提示需要用到15, 18, 21个模块的输出。 yolov8的实例分割用了y…

Pandas包构建DataFrame的几种方式

1. Pandas Pandas是python的一个第三方包&#xff0c;是一个结构化数据工具集&#xff0c;能够更加灵活、快速的对数据进行清洗和处理&#xff0c;适用于单击大数据量的数据分析和数据开发 使用pandas包之前&#xff0c;首先安装 pip install -i https://pypi.tuna.tsinghua.…

【STM32】STM32G系列使用CORDIC模块加速计算

1.前言 STM32G431系列产品内置了CORDIC运算单元&#xff0c;可以用来加速数学计算&#xff0c;如三角函数、取模、开方等。适合大量数据进行相同的运算操作。配合DMA可以大大节省CPU计算开销。 2.CubeMX配置 使用CORDIC模块无需配置参数&#xff0c;若采用DMA方式则只需配置…

JavaWed第三章:JavaScript的全面知识

目录 前言 一.JavaScript的简介 &#x1f496;概念 &#x1f496;学习内容 二.JavaScript的引入方式 &#x1f496;内部脚本 &#x1f496;外部脚本 三.JavaScript的基础语法 &#x1f496;语法的书写 &#x1f496;变量 ✨ 全局变量 ✨局部变量 ✨常量 &a…

Vue3使用$refs获取节点生产环境undefined-使用getCurrentInstance-ctx应改用proxy

vue3项目&#xff0c;在使用refs获取节点&#xff0c;开发环境正常&#xff0c;生产环境报错 console.log(getCurrentInstance()) internalInstance.ctx, internalInstance.proxy 开发环境正常-生产环境报错 internalInstance.ctx 生产环境获取不到值 ctx打包后在生产环境下是获…

激光SLAM(一):点云基础知识

点云基础知识 一、激光雷达介绍1. 机械旋转式雷达2. 固态雷达 二、测量模型与点云1. Range-Azimuth-Elevation&#xff08;RAE&#xff09;- XYZ2. 点云的Packets表示3. 点云的鸟瞰图表示4.Range Image5.TSDF 三、点云的近邻关系Brute-force KNN栅格、体素KD-tree寻找近邻四叉树…

Visual Studio Code系列--CMake Tools使用说明

一、目的 在linux系统上开发程序&#xff0c;一般都是使用vimgccgdb进行的&#xff1b;但是为了开发效率我们也会使用Visual Studio Code进行开发&#xff0c;毕竟有界面的开发调试还是更加友好一些。 老牌程序员肯定都知道make构建工具&#xff0c;但是其晦涩的语法还是难住不…