1.前言
哈喽大家好啊,今天来给大家分享c中static的使用,希望能对大家有所帮助,请大家多多点赞,收藏支持我哦~
2.正文
在讲解static之前,先给大家铺垫三个概念,方便大家理解。
2.1三则知识铺垫
2.1.1作用域与生命周期
2.1.1.1作用域
作用域(scope)主要用来控制变量、函数或对象在程序中的可见性和生命周期。具体来说,作用域限定了一个变量、函数或对象在代码中的哪一部分可以被访问和使用。作用域的种类包括全局作用域、局部作用域和块级作用域。
2..1.1.2生命周期
生命周期,也指生存期(Lifetime),通常指的是一个对象、变量或数据结构在内存中存在的时间长度,即从它被创建或分配内存开始,到它不再被需要并被销毁或释放内存为止的这段时间。
3..1.1.3作用域和生命周期的联系
变量的作用域决定了它在代码中的可见性,而生存期决定了它在内存中的存在时间。虽然作用域和生存期经常是相关的,但它们不是同一个概念。例如,在C++中,一个局部变量在其作用域内是可见的,并且当控制流离开其定义的作用域时,它的生存期就结束了。总而言之,一个关注存活时间,另一个关注可适用范围。
2.1.2内存
相信读者会有一个疑问,我们static为什么要讲内存呢,因为static的使用本质上牵扯到一些内存的概念,将这里理解了就会对static的使用带来极大的帮助。
- 栈区是一种后进先出的数据结构,用于存储程序运行时的局部变量和函数调用信息。当一个函数被调用时,其局部变量和函数参数会被分配到栈上。当函数返回时,这些变量会自动被销毁,栈的空间会被回收。。
- 堆区是用于动态分配内存的区域,通常用于存储程序中需要在运行时进行分配和释放的数据。
- 静态区(也称为全局区)用于存储程序中声明为静态的全局变量和静态局部变量。这些变量在程序运行期间都存在,并且它们的值在函数调用之间保持不变。静态区是在编译时分配内存空间的,因此其大小和位置在程序运行期间是固定的。静态区的生命周期与整个程序的执行周期相同,直到程序结束才由系统释放内存。
3.1.3链接属性
链接属性分别包括外部链接属性和内部链接属性。详细解释如下:
- 外部链接通常指的是程序中定义的标识符(如全局变量或函数)在多个编译单元(通常是源文件)之间的可见性和共享性。当一个标识符被声明为具有外部链接时,它可以在整个程序的不同部分中被访问和引用,就好像它们是同一个实体一样。
- 内部链接(也称为静态链接)是指标识符的作用域限制在其定义的编译单元内。与外部链接不同,具有内部链接的标识符在链接过程中不会暴露给其他编译单元,也不会与其他编译单元中的同名标识符发生冲突。
2.2static的使用
上面铺垫了这么多,接下来开始上正餐:
2.2.1修饰局部变量
接下来我举例子会使用包含俩个函数的代码:
第一段代码:
#include <stdio.h>
void func() {
int i = 0;
i++;
printf("%d\n", i);
}
int main() {
for (int i = 0; i < 5; i++) {
func();
}
return 0;
}
输出结果如图:
我们发现,上段没有实现逐个打印1,2,3,4,5的功能,那是因为func函数中i一旦完成便被销毁下一次for循环再进行func函数时,便还是重新创建i=0的操作。
第二段代码:
#include <stdio.h>
void func() {
static int i = 0;
i++;
printf("%d\n", i);
}
int main() {
for (int i = 0; i < 5; i++) {
func();
}
return 0;
}
输出结果如图:
经过static的修饰后,我们发现可以输出1,2,3,4,5了。因此我们可以得出,static的修饰本质上是使变量的生命周期得到了改变,i这个局部变量本来是储存在栈区,经修饰后储存在了静态区,特征就相当于全局变量了,生命周期延长,但作用域不变。
2.2.2修饰全局变量
局部变量经过static的修饰以后使用可以相当于全局变量,那么static修饰全局变量会有什么影响呢。
为了能够表现出static修饰全局变量后的效果,这里要引用一个extern。
extern 是⽤来声明外部符号的,如果⼀个全局的符号在A⽂件中定义的,在B⽂件中想使⽤,就可以使用extern。
int a = 1;
#include<stdio.h>
int main() {
extern int a;
printf("%d", a);
return 0;
}
这个代码可以正常输出1;
代码2:
static int a = 0;
#include<stdio.h>
int main() {
extern int a;
printf("%d", a);
return 0;
}
用编译器一编译发现,这段代码没有办法正常输出。由此我们可以得出被static修饰后的全局变量只能在当下源文件去使用,全局变量本身是被默认具有外部连接属性,被修饰后该变量由外部连接属性变成内部连接属性,即使声明了,也是无法正常使用。
使⽤建议:如果⼀个全局变量,只想在所在的源⽂件内部使⽤,不想被其他⽂件发现,就可以使⽤ static修饰。
2.2.3修饰函数
接下来再给大家附上俩段代码
代码1:
int func(int x, int y) {
return x + y;
}
#include<stdio.h>
extern int func(int x ,int y);
int main() {
int a = 0, b = 0;
scanf("%d%d", &a, &b);
printf("%d",func(a, b));
return 0;
}
这段代码运行后发现可以实现调用加法函数的功能,即能正常输出a+b的值。
代码2:
extern int func(int x, int y) {
return x + y;
}
#include<stdio.h>
extern int func(int x ,int y);
int main() {
int a = 0, b = 0;
scanf("%d%d", &a, &b);
printf("%d",func(a, b));
return 0;
}
调试后发现,这段代码无法正常输出,原因和static修饰全局变量类似,函数本身带有外部链接属性,经过extern修饰后,转换成内部链接属性,则函数的调用仅限于当前源文件中了。
使⽤建议:如果⼀个函数,只想在所在的源⽂件内部使⽤,不想被其他⽂件发现,就可以使⽤ static修饰。
3.小结
今天的分享到这里就结束了,希望喜欢的朋友多多支持我哦~