c语言中的静态函数

c语言中的静态函数,c,static,C,Static,我认为C中声明为静态的函数只有在我定义的文件中才可见。在下面的示例中,静态变量在另一个文件中可见。我不太确定是否是因为以下原因: 主要条款c: #include "test.c" int main() { test(); } 测试c: static void test() { // do something here } void foo() { // do something different here } 如果它只处理头文件,那么它不是完全无用吗?如果我想隐藏

我认为C中声明为静态的函数只有在我定义的文件中才可见。在下面的示例中,静态变量在另一个文件中可见。我不太确定是否是因为以下原因:

主要条款c:

#include "test.c"

int main() {
    test();
}
测试c:

static void test() {
    // do something here
}

void foo() {
   // do something different here
}
如果它只处理头文件,那么它不是完全无用吗?如果我想隐藏一个函数,那么我不会在头文件中提到它

#include
是一个预处理器指令。当预处理器(在编译之前运行)看到它时,它会将包含的文件的内容复制到那里。所以你最终把它放在同一个文件里

如果它只与头文件一起工作,那么它不是完全无用吗?如果我想隐藏一个函数,那么我不会在头文件中提到它

当然,但在头文件中不提及它不会“隐藏”它。头文件不会被编译,如果您将原型放在那里,它将作为编译器的线索


静态函数的优点是,它们在文件外部不可见,因为它在对象文件中不是全局的。这允许您在其他文件中使用相同的符号(名称)进行其他操作,而不会产生冲突。

C中声明为静态的函数仅在包含该符号的翻译单元中可见,这意味着不会导出该符号。它与文件无关,而是与翻译单位有关。在您的例子中,只有一个翻译单元main.c,它包含另一个文件的内容,因此定义了main、test和foo;main和foo将被导出,而test不会被导出。

如果
main.c
test.c
是独立的翻译单元,那么您就对了。但是,通过将
test.c
的文本直接包含到
main.c
中,您已经创建了一个翻译单元,因此静态函数对
main
可见。它的行为就像您将其全部编写为一个文件一样

您不希望包含包含变量或函数定义的文件;这是在编译或链接时遇到多个定义错误的好方法。相反,
#include
文件的内容应限于类型定义、非定义变量声明和函数声明

您可以创建一个文件
test.h
,如下所示:

#ifndef TEST_H  // include guard; prevents this file from being processed
#define TEST_H  // more than once per translation unit

void foo();     // declaration for foo; this is the only function we're exposing

#endif
然后将
main.c
重写为

#include "test.h"

int main(void)
{
  test();
  return 0;
}
然后分别编译
main.c
test.c
,然后链接生成的对象文件以创建可执行文件:

gcc -c main.c
gcc -c test.c
gcc -o test main.o test.o

此时,您将得到一个链接器错误,其顺序为“未定义引用”,因为
test
的符号尚未导出

是的,这是因为包含。你应该只包括头文件,
.h
@jweyrich:真的吗?预处理器对符号一无所知,它只解析由字符组成的标记。你能解释一下#包含c文件与直接粘贴其内容有何不同吗?@flix请尝试只包含*.h文件而不是*.c文件。@K-ballo:这是一种惯例,应该!=不能。我强烈建议任何C程序员都应该遵循这个惯例,以使其他程序员的生活更轻松。头文件以.h结尾(即不是代码)