static - 仅用于限制范围?

时间:2009-11-25 08:13:37

标签: c static scope

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中有任何其他用途吗? (除了限制变量的范围,如上所示?)

7 个答案:

答案 0 :(得分:12)

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

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

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

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

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:4)

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

答案 3 :(得分:3)

增加Kinopiko答案的一个例子:

#include <stdio.h>

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;
}

答案 4 :(得分:1)

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

static的另一种用法是在函数内部:

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

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

答案 5 :(得分:1)

变量可能有三种存储方式:

  1. 在程序的静态区域
  2. 在堆栈上(在函数调用期间)
  3. On Heap(使用new / malloc分配时)
  4. 全局变量始终存储在静态区域中。但是要在静态区域中存储局部变量,您需要关键字static。由于静态变量未在堆栈上分配,因此您可以在后续调用中访问该变量 全局范围内的static关键字也提供了可变的内部链接。因此,使用extern限定符无法从其他文件访问该变量。

答案 6 :(得分:1)

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

// file1.c中

#include <stdio.h>
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
  4. 关于静态变量的一个重要的事情是它有内部链接。所以我们可以将这个变量访问到一个特定的文件。它们被定义(不在其他文件中)。

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

    // file2.c中

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

    输出:3 这被称为外部联系。