首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

C语言基础:static的使用

  • 23-09-22 01:23
  • 3844
  • 13504
blog.csdn.net

本文结合工作经验,研究C语言中static关键字的用法。

文章目录

  • 1 static关键字概念
  • 2 用法与使用场景
    • 2.1 修饰全局变量
      • 2.1.1 代码示例
      • 2.1.2 使用场景
    • 2.2 修饰函数
      • 2.2.1 代码示例
      • 2.2.2 使用场景
    • 2.3 修饰局部变量
      • 2.3.1 代码示例
      • 2.4.2 使用场景
  • 3 总结

1 static关键字概念

static关键字在C语言中非常常用,博主工作中常见三种用法:修饰全局变量、修饰局部变量以及修饰函数。通过static关键字的修饰,可以使被修饰的变量或函数只在作用域中有效,类似一种私有化的机制。

2 用法与使用场景

2.1 修饰全局变量

2.1.1 代码示例

在函数外定义的变量称为全局变量。全局二字表示,在其他的c文件中也可以调用这个变量。

例如如下代码demo1.c,main.c:

//demo1.c

int demo_a;

void demo1(void)
{
	demo_a = 10;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
//main.c

#include 

extern int demo_a;
extern void demo1(void);

int main()
{
    demo1();
    printf("demo_a = %d
", demo_a);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

首先,在demo1.c中定义了一个全局变量demo_a,以及一个函数demo1(void)用于将10赋值给全局变量。

然后,在main函数中通过extern关键字,外部声明全局变量demo_a和函数demo1(void)。在main函数内部先通过调用demo1()将demo_a赋值为10,再编译软件打印出来。

打印在控制台上的结果如下:

在这里插入图片描述
这个demo对熟悉C语言的人来说是小菜一碟。之所以能在其他c文件中调用到demo_a的值,是因为全局变量的作用域为整个工程的c文件中。

接着在这个基础上,如果加上关键字static修饰全局变量demo_a,如下图:

//demo1.c

static int demo_a;//加上关键字static修饰全局变量demo_a

void demo1(void)
{
	demo_a = 10;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

再编译一下就会报错:
在这里插入图片描述
这里报错的意思是,在软件链接的过程中,搜索工程中所有的c文件都无法找到demo_a这个变量。因为static关键字将demo_a这个变量的作用域限定在demo1.c这个文件中才可以使用了,外部其他文件即使extern声明了也无法引用。

2.1.2 使用场景

博主工作经验中,这种用static修饰全局变量,是为了将该全局变量限定在自身的c文件中使用,防止其他c文件随意地篡改掉。例如上一节中的做法,外部文件是完全无法访问到demo_a的值的。

如果想要获取静态全局变量的数值该怎么办呢。可以通过调用函数返回值获取,把代码改成下图所示。

//main.c

#include 

extern int demo1(void);

int main()
{
    int demo_a = demo1();    
    printf("demo_a = %d
", demo_a);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
//demo1.c

static int demo_a;

int demo1(void)
{
	demo_a = 10;
	return demo_a;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

将demo_a的数值通过demo1()函数返回给main函数,这样外部就可以获得该静态全局变量的值。注意一点,demo1.c和main.c文件中都出现了demo_a变量,但不是一回事,一个是静态全局变量,另一个是函数中的局部变量。也就是说,在main函数中将局部变量demo_a的值改成其他的值(例如20),是不会影响到demo1.c文件中的静态全局变量demo_a的。这样,也就使得外部文件只能读不能写,达到了既能给外界传递信息,又能防篡改的效果。

2.2 修饰函数

2.2.1 代码示例

将上一节的代码稍微改一下,如下:
例如如下代码demo1.c,main.c:

//demo1.c

int demo_a;

static void demo1(void)
{
	demo_a = 10;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
//main.c

#include 

extern int demo_a;
extern void demo1(void);

int main()
{
    demo1();
    printf("demo_a = %d
", demo_a);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

将demo1.c中的demo1(void)函数定义之前加上static关键字,就成为了静态函数。这时候在main函数中通过extern外部声明demo1(void)函数,就无法调用了,运行结果如下:
在这里插入图片描述
报错就和上一节类似,找不到demo1(void)这个函数的定义。static关键字也将这个函数的作用域限定在本文件中。

把代码稍微改一改,改成如下嵌套调用的形式:

//main.c

#include 

extern int demo_a;
extern void demo(void);

int main()
{
    demo();
    printf("demo_a = %d
", demo_a);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
//demo1.c

int demo_a;

static void demo1(void)
{
	demo_a = 10;
}

void demo(void)
{
	demo1();//demo()函数中调用demo1()静态函数
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这样在运行一下,就能正常地打印出来了。

这说明static修饰的函数只能在该文件内部被别的函数调用,不能在别的文件通过extern外部声明调用到。

2.2.2 使用场景

博主在工作中遇到static修饰函数地使用场景是,一个文件地函数中划分了若干个功能,提取为几个子函数,将这几个子函数用static修饰成静态函数。这样做防止外部函数调用子函数,只限制在该文件内调用。

例如如下代码:

//demo1.c

static void demo1(void)
{
	demo_a = 10;
}

static void demo1(void)
{
	printf("demo_a = %d
", demo_a);
}

void demo(void)
{
	demo1();
	demo2();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

demo(void)函数调用了自身c文件的两个其他的静态函数,这两个静态函数分别实现两个功能:赋值与打印。然后别的外部函数可以调用非静态的demo(void)函数,从而执行下面的两个子函数。

2.3 修饰局部变量

局部变量定义在某个函数内部,作用域仅限于该函数,函数运行完毕后就被释放掉了。如果在局部变量之前加上static修饰,就会不一样。

2.3.1 代码示例

首先举个简单的局部变量的例子:

//main.c

#include 

void demo(void)
{
    int a = 0;
    a++;
    printf("%d ", a);
}

int main()
{
    for (int i = 0; i < 5; i++)
    {
        demo();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在demo()函数中定义一个局部变量a,初始化为0,接着自加1并打印出来。在main函数中通过for循环调用5次demo()函数,查看5次的打印结果如下:
在这里插入图片描述
这里打印出来了5个1,是因为每次进入demo()函数,int a都会新开辟一个栈空间存储这个临时变量,并初始化为0。接着自加1并打印,所以每次都输出1。

接着,稍微改一下代码,在int a局部变量定义之前加上static修饰,代码改为如下:

//main.c

#include 

void demo(void)
{
    static int a = 0;//加上static修饰
    a++;
    printf("%d ", a);
}

int main()
{
    for (int i = 0; i < 5; i++)
    {
        demo();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

再次运行程序,打印如下:
在这里插入图片描述
打印的结果变为了12345,也就是说,每次调用demo()函数后,a的值保留到了下一次调用,再自加1打印出来。

这里的原因是static关键字将局部变量a变成了静态局部变量。静态局部变量的特点是不会在函数调用后释放掉,而是在编译好了以后直接分配一个固定的地址并直接初始化为0(这一点类似于全局变量)。当每次demo()函数运行时,由于a已经预先定义好了,就不会执行static int a = 0;这一句语句。

2.4.2 使用场景

static局部变量能达到一个保留变量数值不被释放掉的效果,这一点在嵌入式C语言开发中非常有用。在周期调度某个函数时,static修饰的局部变量就可以保留上一周期的值。

举个一阶滤波算法的例子,一阶滤波公式如下:

Y(n) = α*X(n) + (1−α)*Y(n−1)
  • 1

一阶滤波的输出值需要依赖上一次的输入值,所以就可以用一个静态局部变量存储本周期的输出值,到了下次调用函数的时候就成为了上次的输出值。参考如下代码。

#define Alpha 0.8

void first_order_filter(float input,float* output)
{
    static float output_previous = 0;
    *output = (1 - Alpha) * output_previous + input * Alpha;
    output_previous = *output;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3 总结

在工作中常见以上三种static关键字的使用方法。

>>返回个人博客总目录

文章知识点与官方知识档案匹配,可进一步学习相关知识
C技能树首页概览160872 人正在系统学习中
注:本文转载自blog.csdn.net的chhttty的文章"https://blog.csdn.net/u013288925/article/details/130691462"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top