static – 仅用于限制范围?

C中的static关键字是否仅用于将变量的范围限制为单个文件?

我需要知道我是否理解这一点。 请假设以下3个文件,

在file1.c

 int a; 

file2.c中

 int b; 

file3.c中

 static int c; 

现在,如果3个文件一起编译,那么变量“a”和“b”应该具有全局范围,并且可以从3个文件中的任何一个访问。 但是,变量“c”是静态的,只能从file3.c访问,对吗?

static在C中有任何其他用途吗? (除了限制变量的范围,如上所示?)

static关键字在C中有两个不同的用途,我称之为持续时间(对象的生命周期)和可见性(可以使用对象)。 请记住,C标准实际上对这两个概念使用了不同的单词,但我发现在教授语言时最好先使用日常术语。

在文件级别(在任何函数之外)使用时,它控制可见性。 在文件级别定义的变量的持续时间已经定义为程序的整个持续时间,因此您不需要static

文件级别的静态变量对于翻译单元之外的任何内容都是不可见的(链接器无法看到它)。

在function级别(函数内部)使用时,它控制持续时间。 那是因为可见性已被定义为该function的本地。

在这种情况下,变量的持续时间是程序的整个持续时间,并且在函数的调用之间保持值。

您滥用术语“范围”。 C中的static与范围完全无关。

范围是实体名称(变量,函数,类型名称等)可见的区域。 在C语言中,“文件范围”是有史以来最大的范围。 出于这个原因,将任何内容限制为单个文件是没有意义的:没有什么比这更大的了。 在C中没有“全局范围”这样的东西。术语“全局范围”有时是非正式使用的,但在这种情况下它与“文件范围”具有相同的含义。

同样,C中的static范围完全无关。 C中的static影响对象的存储持续时间和标识符的链接 。 当与对象(变量)一起使用时, static给对象提供静态存储持续时间 (即,只要程序运行,对象就存在)。 并且,当与非本地对象或函数的标识符一起使用时,它为它们提供内部链接 ,这意味着相同的标识符指的是单个转换单元(定义实体的位置)内的相同实体,而不是其他转换单元。

static也在函数定义中用于定义一个变量,该变量在函数调用之间保持其值。 我在这里找到了一个例子 。 相反,每次函数调用重新创建的变量称为自动变量。

一个增加Kinopiko答案的例子:

 #include  int foo() { static int foo = 0; return ++foo; } int main() { printf("%i\n", foo()); // 1 printf("%i\n", foo()); // 2 } 

例如,这可用于返回指向本地函数变量的安全指针。 或者在Objective-C中,它有时用于防止重复的类初始化:

 - (void) initialize { static BOOL initialized = NO; if (initialized) return; // …perform initialization… initialized = YES; } 

变量可能有三种存储:

  1. 在程序的静态区域
  2. 在堆栈上(在函数调用期间)
  3. 在堆上(当您使用new / malloc分配时)

全局变量始终存储在静态区域中。 但是要在静态区域中存储局部变量,您需要关键字static 。 由于静态变量未在堆栈上分配,因此您可以在后续调用中访问该变量。
此外,全局范围内的static关键字提供了可变的内部链接。因此,使用extern限定符无法从其他文件访问该变量。

您是对的,这称为“静态链接”:声明为static的符号仅在定义它的编译单元中可用。

static的另一个用途是在函数内部:

 void f() { static int counter = 0; counter++; // ... } 

在这种情况下,变量仅初始化一次并通过该函数的不同调用保持其值,就像它将是一个全局变量一样。 在此示例中, counter变量计算调用函数的次数。

内部联系与外部联系的例子

//file1.c

 #include  int glb_var=3;//global variable int func(); //prototype of function int main() { func(); func(); func(); return 0; } int func() { static int counter=0;//static varible printf("val of counter=%d",counter); counter+=5; return 0; } 

当我们编译这个程序并运行这个程序时,os会将这个程序加载到内存中。接下来会发生一些事情:

  1. glb_var标识符将存储在初始化的数据段中。

  2. 计数器标识符将存储在名为“.bss”的未初始化数据段中。

  3. 静态变量初始化一次并且值在函数调用期间持续存在。因为静态变量存储在数据段中而非堆栈中,因此静态变量在函数调用期间保持不变。 因此程序的输出将是:0 5 10

关于静态变量的一个重要的事情是它具有内部链接。因此我们可以将此变量访问到特定文件。它们是在其中定义的(不在其他文件中)。

我们可以使用extern关键字访问其他文件中的全局变量glb_var。 例如:

//file2.c

 #include  extern glb_var; //for declaration of this variable int main() { if(glb_var) { printf("glb_var=%d",glb_var); } } 

输出:3这称为外部链接。