为什么在C语言中要声明变量或函数为静态的?

22

我理解static的作用,但不知道为什么要使用它。它只是为了保持抽象层吗?


1
复制 https://dev59.com/lXRB5IYBdhLWcg3wn4UL。 - Eli Bendersky
4个回答

26

在C语言中,使用 static 有几个原因。

当用于函数时,其意图是创建抽象。C源代码文件范围的原始术语为“翻译单元”。静态函数只能从同一翻译单元内部访问。这些静态函数类似于C ++中的私有方法,可以自由解释(在这种比喻中,翻译单元定义了一个类)。

全局层面上的静态数据也不可从翻译单元外部访问,这也可用于创建抽象。此外,所有静态数据都初始化为零,因此可以使用 static 来控制初始化。

在本地(“自动”)变量级别上使用静态,是用于抽象化函数的实现,该函数在多次调用之间保持状态,但避免使用翻译单元范围内的变量。再次强调,由于静态限定,这些变量被初始化为零。


1
我不明白,如果你在一个 .c 文件中的函数或变量上添加 static 关键字,那么该文件不是永远不会被包含在其他任何地方吗?因此,无论你是否将其标记为 static,该函数/变量始终是本地的,这不会使 static 变得无关紧要吗?有人能解释一下吗? - Matias Chara

9
关键字static有几种用途; 在函数外部,它只是将函数或变量的可见性限制为编译单元(.c文件)中出现的函数或变量。这样,函数或变量就不会成为全局变量。这是一件好事,它促进了一种“需要知道”的原则(不要暴露不需要暴露的内容)。此类静态变量被零初始化,但当然全局变量也被零初始化,因此静态关键字本身不负责零初始化。
变量也可以在函数内部声明为静态。这个特性意味着变量不是自动的,即不会在每次调用函数时在堆栈上分配和释放。相反,变量在静态数据区中分配,它被初始化为零,并持续存在于程序的生命周期中。如果函数在一个调用中修改它,新的修改值将在下一个调用中可用。这听起来很不错,但是“auto”是默认选项,而函数内的“static”变量应该谨慎使用。简而言之,自动变量更加节省内存,并且如果您希望函数线程安全,则必不可少。

7
static 既可以用作存储类别说明符,也可以用作链接说明符。作为链接说明符,它将全局变量或函数的作用域限制在单个编译单元中。这允许一个编译单元拥有与其他编译单元相同标识符名称的变量和函数,但不会导致冲突,因为这些标识符对于链接器来说是“隐藏”的。例如,如果您正在创建一个库并需要内部的“辅助”函数,但这些函数不能与用户代码发生冲突,则此功能很有用。

作为应用于本地变量的存储类别说明符,它具有完全不同的语义,但您的问题似乎暗示了您正在引用静态链接。


1

C中的静态函数

在C中,默认情况下,函数是全局的。在函数名前加上“static”关键字可以使其变为静态函数。例如,下面的函数fun()是静态的。

static int fun(void)
{
  printf("I am a static function ");
}

与C语言中的全局函数不同,对于静态函数的访问仅限于声明它们的文件。因此,当我们想要限制函数的访问时,我们将其设置为静态。另一个将函数设置为静态的原因是可以在其他文件中重用相同的函数名称。
例如,如果我们将以下程序存储在一个文件file1.c中:
/* Inside file1.c */
static void fun1(void)
{
  puts("fun1 called");
}

请将以下程序存储在另一个名为file2.c的文件中。

/* Iinside file2.c  */
int main(void)
{
  fun1(); 
  getchar();
  return 0;  
}

现在,如果我们使用命令gcc file2.c file1.c编译上面的代码,我们会得到错误undefined reference to fun1。这是因为在file1.c中,fun1被声明为static,无法在file2.c中使用。请参见此处的解释,其中包含代码来源。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接