如果函数声明不在头文件中,那么静态关键字是否必要?

时间:2014-07-01 12:58:30

标签: c static

如果函数声明不在头文件(.h)中,而是仅在源文件(.c)中,为什么需要使用 static 关键字?当然,如果你只在.c文件中声明它,那么其他文件就不会看到它,因为你不应该#include .c文件,对吧?

我已经阅读了很多关于此的问题和答案(例如。herehere),但不能完全了解它。

3 个答案:

答案 0 :(得分:5)

static的作用是无法通过头文件在其他模块中声明和调用函数。

回想一下,C中包含的头文件只是文本替换:

// bar.c
#include "header.h"

int bar()
{
    return foo() + foo();
}

// header.h
int foo(void);

被预处理成为

int foo(void);

int bar()
{
    return foo() + foo();
}

事实上,你可以取消header.h,并且首先以这种方式写bar.c。同样,foo的定义不需要在任何一种情况下都包含标题;包括它只是添加一个检查,foo的定义和声明是一致的。

但是如果你要将foo的实现更改为

static int foo()
{
    // whatever
    return 42;
}

然后foo的声明将在模块和头文件中停止工作(因为头文件只能被替换为模块)。或者实际上,声明仍然“有效”,但它会停止引用您的foo函数,当您尝试调用foo时链接器会抱怨它。

使用static的主要原因是为了防止链接器冲突:即使foobar在同一个模块中,并且模块外部没有任何内容称为foo,它不是static,它仍会与名为static的任何其他非foo函数冲突。第二个原因是优化:当函数为static时,编译器确切地知道程序的哪些部分调用它以及使用什么参数,因此它可以执行常量折叠,死代码消除和/或内联。

答案 1 :(得分:4)

static关键字会降低函数对文件范围的可见性。这意味着您无法在其他单元中本地声明该函数并使用它,因为链接器不会将其添加到全局符号表中。这也意味着您也可以在其他单位中使用该名称(每个文件中可能有static void testOutput();,如果省略static则无法使用{。}}。

根据经验,您应该尽可能保持符号的可见性。因此,如果您不需要外部例程(并且它不是某个界面的一部分),请保留static

答案 2 :(得分:2)

  1. 它允许您在不同的源文件中具有相同名称的函数,因为编译器会为每个静态函数的名称添加一个隐式前缀(基于函数所在文件的名称),从而防止多重定义链接错误。

  2. 帮助维护代码的人知道该函数不作为接口的一部分公开,并且仅在文件内部使用(非静态函数可用于其他源文件即使,如果未使用extern关键字在任何标头文件中声明。