从浅入到深入了解static关键字

我们先来介绍下局部变量中static关键字的使用

局部变量:一般泛指方法里面声明的变量(一般局部变量不会自动初始化,静态局部变量自动初始化为0)
1.先来演示一下普通局部变量在程序中的变化过程

void run();//测试普通局部变量 
void run(){
	int i=1;
	printf("%d\n",i);
	i++;
	printf("%d\n",i);
}
int main(){
	printf("普通局部变量的结果\n"); 
	run();
	run();
}

结果
在这里插入图片描述

分析:当我们在函数中声明一下普通变量,我们可以理解它其实是存储在 进程栈空间,当函数调用结束后,里面的函数会被立即释放。

程序栈有啥

通常有局部变量,调用函数参数,被调函数返回地址,被调函数栈顶地址,函数返回值(返回值通常是由寄存器EAX返回的,因为速度较快)等。
在这里插入图片描述
程序栈介绍

2.接下来该演示静态局部变量在程序中的变化过程

void run2();//测试静态局部变量
void run2(){
	static int  j=1;
	printf("%d\n",j);
	j++;
	printf("%d\n",j);
}
int main(){
	printf("静态局部变量的结果\n"); 
	run2();
	run2();
}

结果
在这里插入图片描述

分析:在这里发现当第一次释放函数时,值并没有被释放出来,而是接着被第二个函数使用。这是为什么?原因是被static修饰的代码(不论是局部还是全局)都被放到了全局数据区生命周期很长(为一次程序的运行过程)并且只被初始化一次

3.有的同志又有问题了,C语言运行时内存到底是怎么划分的?

C语言运行时内存大致分为四个数据区:常量区、全局数据区(静态区)、堆区、栈区
在这里插入图片描述
常量区:存放常量(程序在运行的期间不能够被改变的量,例如: 10,字符串常量”abcde”, 数组的名字等)
静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放
堆区:由程序员调用malloc()函数来主动申请的,需使用free()函数来释放内存,若申请了堆区内存,之后忘记释放内存,很容易造成内存泄漏
栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。
内存分区的详解介绍,引用大佬的

4.回归正题,学到这其实某些同学又有问题了,TM的我是闲的吗,我直接用全局变量来定义就是了,用什么static?好,这个疑问你先留着,看完下一个内容你就understand了

void run();//测试普通局部变量 
void run2();//测试静态局部变量
void run3();//不同函数声明同名的一个静态局部变量
void run(){
    int i=1;
	printf("%d\n",i);
	i++;
	printf("%d\n",i);
}
void run2(){
	static int  j=1;
	printf("%d\n",j);
	j++;
	printf("%d\n",j);	
}
void run3(){
	static int j=1; 
	printf("%d\n",j);
} 	
int main(){
	printf("普通局部变量的结果\n"); 
	run();
	run();
	printf("\n");
	printf("静态局部变量的结果\n"); 
	run2();
	run2();
	printf("再次调用局部静态变量\n"); 
	run3();//猜一下结果输出什么?
	
}

结果:
在这里插入图片描述
自己思考一下,给你一个小小的结论(如果不理解,继续看下面的演示)

静态变量的作用域其实是要看它所在的区域的,如果你在函数内部声明,O他的作用域就是这个函数,如果在外面声明,那作用域就是这个文件。

说完了局部那就再说一下全局的呗

全局变量:定义在函数外部的变量

问题来了,那全局变量和静态全局变量有啥区别?
我们先看看静态全局变量在多文件之间的调用过程

file.h

#include <stdio.h>
 
void printStr();
我们在file1.c中定义一个静态全局变量hello, 供file1.c中的函数printStr访问

#include "file1.h"
 
static char* hello = "hello cobing!";
 
void printStr()
{
	printf("%s\n", hello);
}
file2.c是我们的主程序所在文件,file2.c中如果引用hello会编译出错

#include "file1.h"
 
int main()
{
	printStr();
	printf("%s\n", hello);
	return 0;
}

结果: 报错hello未声明

如果我们将file2.c改为下面的形式:编译顺利通过

#include "file1.h"
int main()
{
	printStr();
	return 0;
}

结论:

静态全局变量,只在本文件可以用,虽然整个程序包含多个文件, 但静态全局变量只能用在定义它的那个文件里,却不能用在程序中的其他文件里。
普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了

最后一个问题,加static的函数

我想学了上述问题,应该运行结果很容易就猜到了。

file.c
#include <stdio.h>
static void fun(void)
{
    printf("hello from fun.\n");
}

int main(void)
{
    fun();
    fun1();

    return 0;
}
file2.c
#include <stdio.h>

static void fun1(void)
{
    printf("hello from static fun1.\n");
}

结果: 指定报错,原因对‘fun1’未定义的引用
在这里插入图片描述

改正:

file.c
#include <stdio.h>
static void fun(void)
{
    printf("hello from fun.\n");
}

int main(void)
{
    fun();
    fun1();

    return 0;
}
file2.c
#include <stdio.h>

void fun1(void)
{
    printf("hello from static fun1.\n");
}

static函数与普通函数有什么区别?

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件。

总结:

其实static我们可以把他理解成Java中的private属性,只能供内部成员去访问,那平时做项目的时候有什么用呢?当做一个庞大的工程时,我们做某一模块的功能,我们可能让某些代码在这一个单独的模块内起作用,那我们就用到了static,出了这个模块,别人就不认识你了。

本文中章引用两位大佬的文章,并结合自己的理解来写了下面内容。如有侵权,联系立即删除。
https://blog.csdn.net/keyeagle/article/details/6708077
https://blog.csdn.net/guotianqing/article/details/79828100

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于弋gg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值