分析C语言static关键字的作用
目录- 先来看一个案例
#include <stdio.h>
int a=5;
void show_val(void)
{
int b=3;
static int c=2;
a+=5;
b+=5;
c+=5;
printf("a = %d,b = %d,c = %d\n",a,b,c);
c = b;
}
int main(void)
{
int b=0;
static int c;
a += 3;
show_val();
b += 3;
show_val ();
return 0;
}
第一次打印结果:
a = 13,b = 8,c = 7
第二次打印结果:
a = 18,b = 8,c = 13
- 为什么会有这样的结果呢?主要受
static
关键字的影响,下面就来分析static
关键字的作用。
1.静态存储期(局部变量使用static时)
1.当static关键字用于函数内的局部变量时,它改变了该变量的存储期。通常,函数内的局部变量具有自动存储期,这意味着它们在进入函数时创建,在离开函数时销毁。
2.但是,当局部变量被声明为
static
时,它获得了静态存储期,这意味着该变量在程序开始时分配内存,在程序结束时释放内存。
3.静态局部变量的初始值只会在第一次进入函数时设置,之后调用函数时不会再次设置。因此,静态局部变量可以用来跟踪函数被调用的次数,或者记住跨函数调用之间的某些状态。
//例如:
void Function() {
static int count = 0;
count++;
printf("Function has been called %d times\n", count);
}
// 多次调用 counterFunction 会显示递增的计数
int main()
{
for(int i = 0;i < 5,++i)
{
function();
}
return 0;
}
2.静态全局变量
1.全局变量可以使用
static
关键字进行修饰。但是,当我们在全局作用域(即文件级作用域)中使用static
修饰一个变量时,它的意义与在函数内部(局部变量)使用static
修饰变量时有所不同。2.我们知道,当在函数内部使用
static
修饰一个变量时,该变量在函数调用之间保持其值。这意味着它只会在第一次调用该函数时被初始化,并在随后的函数调用中保持其值。3.当在全局作用域中使用
static
修饰一个变量时,该变量具有内部链接。这意味着该变量只在其定义的文件中可见,对其他文件是不可见的。这通常用于限制全局变量的可见性,防止其他文件意外地访问或修改它。因此,静态全局变量的特性是:
(1)它的作用域是全局的,意味着在程序中的任何函数内部都可以访问它(只要它们有正确的访问权限)。
(2)它的生命周期是整个程序的执行期间,从程序开始到程序结束。
(3)由于它是static
的,所以它的可见性被限制在定义它的文件内部。这意味着如果你试图在另一个源文件中访问这个静态全局变量,你将无法做到(除非使用某种特殊的链接技术,如外部声明)。
//例如:
// file1.c
static int Val = 10;
void func()
{
printf("%d\n", Val);
}
// file2.c
//...
// 这里不能访问 Val,因为它在 file1.c 中是 static 的
//在这个例子中,Val 只在 file1.c 中可见,因此 file2.c 不能访问它。
1.注意:在一个C语言工程项目中,我们往往有很多的
.c
源文件。如果两个或多个.c
源文件定义了相同名字的全局变量(即具有外部链接的变量),那么这会导致链接器错误,因为链接器会在试图将多个目标文件合并成一个可执行文件或库时,发现存在名称冲突的全局符号。2.因为每个
.c
源文件在编译后都会生成一个目标文件(比如.o
文件),这些目标文件包含了源文件中的函数和全局变量的信息。当链接器试图将这些目标文件合并成一个可执行文件时,它会查找所有全局符号的定义,并确保每个符号只被定义一次。因此如果两个或多个目标文件定义了相同的全局变量,链接器会报告一个错误,指出存在重复定义的符号。因此避免在多个.c
源文件中使用相同的变量名尤为重要,(即使全局变量的类型不同,但只要它们的名字相同,并且都是具有外部链接的全局变量,那么在不同的.c
源文件中定义它们仍然会导致链接器错误)。
如下是避免这种情况的方法:
(1)使用不同的变量名:这是最简单的方法,只需确保每个
.c
文件中的全局变量都有唯一的名称。(2)使用
static
关键字:在全局变量的声明前添加static
关键字可以将其作用域限制在单个源文件内。这样,即使两个或多个源文件都包含了相同名称的static
全局变量,链接器也不会报告错误,因为这些变量实际上是在不同的作用域中定义的。(3)使用外部变量声明:在一个
.c
文件中定义全局变量,并在其他需要使用这个变量的.c
文件中使用extern
关键字声明它。这样,所有的.c
文件都共享同一个全局变量的定义。(extern
关键字可以声明一个函数或者一个变量的属性是外部可链接的,意味着可以被外部文件调用。)//例如: // file1.c int val = 10; // 定义全局变量 // file2.c extern int val; // 声明全局变量,但不定义它 // 然后在file2.c中可以使用val
3.static与函数一起使用
当
static
与函数一起使用时,它主要有两个主要用途:文件作用域或内部链接。当你在一个C源文件的文件作用域(即在所有函数之外)中声明一个函数为
static
时,这个函数的链接属性会被改变为内部链接。这意味着该函数只能在声明它的源文件中被访问,而不能从其他源文件中被链接或访问。
这有助于隐藏实现细节,使得库的实现者可以提供某些功能,而不需要暴露这些功能的接口给库的最终用户。
//例如:
static void function()
{
// ......
}
// 其他源文件不能调用function
标签:函数,int,源文件,关键字,static,全局变量,链接,作用
From: https://www.cnblogs.com/lwj294/p/18253428