C语言中静态函数的正确使用方法是什么?

4

我发现在C语言中有两种使用静态函数的方法。

第一种方法是:

afile.h

static void afunc(void); // leaving this out gives errors

afile.c

void afunc(void)
{
   puts("a");
}

void callafunc(void)
{
   afunc();
}

main.c

void afunc(void)
{
   puts("b");
}

int main(void)
{
   afunc(); // prints b
   callafunc(); // prints a
}

另一种方法是:

afile.h

// declare nothing w.r.t. static functions

afile.c

static void afunc(void)
{
   ...
}

main.c

static void afunc(void)
{
   ...
}

这两种使用静态函数的方式哪种是正确的?


8
不应该在.h文件中放置静态函数的原型。它们只在编译单元(.c文件)中可见,因此请将原型放置在C文件的顶部。 - Paul Ogilvie
你不应该在不同的.c文件中声明相同的静态函数。 - Paul Ogilvie
我同意第二种方式几乎总是被使用。但是为什么第一种方式似乎也能够正常工作呢?关于你的第二条评论,如果静态函数是每个文件本地的,那么为什么我不能使用相同的名称(除了可能会引起混淆)? - user395980
第一种方法“有效”,是因为你滥用了 include 指令的功能,来包含函数定义。 - William Pursell
1
@PaulOgilvie:所有声明的唯一作用域是翻译单元或更小。static 影响链接,而不是作用域。 - Eric Postpischil
2个回答

4
这两种使用静态函数的方法,哪一种是正确的?
第二种方法是正确的。
"static void afunc(void);" 是一个函数声明。该函数的定义存在于某处。由于它也是静态的,如果在编译中使用该函数,则该函数的定义也需要在此编译单元中。该函数具有局部链接性。
在第二种情况下,"main.c" 和 "afile.c" 都使用其本地定义的 "afunc(void)"。
不需要向全局命名空间声明 "afunc()" 的存在。没有其他编译单元需要知道 "main.c、afile.c" 的这些本地函数。
通常情况下,第一种方法是不正确的。
第一种情况“可行”,因为 "main.c" 和 "afile.c" 都使用并具有本地定义的 "afunc(void)"。
如果另一个文件 "foo.c()",使用 "#include “afile.h”" 并尝试调用 "afunc()",则除非它也有本地定义的 "afunc()",否则将无法找到匹配的本地 "afunc()"。
"*.h" 更多地告诉全局命名空间使用 " *.c" 中的函数、对象、定义、类型等。这些被标记为 "static" 的东西最好放在顶部的 "*.c" 中供其自己使用,而不是放在 "*.h" 中。
第一种方法在狭窄的情况下可能是正确的。
例如, "afile.h" 声明并定义了一个小的辅助函数,并打算让包括 "afile.h" 的任何 " *.c" 都获得自己本地版本的 "afunc()"。通过使它成为静态的,这些本地 "afunc()" 不会与潜在的全局 "afunc()" 或彼此冲突。

2
拥有头文件的目的如下:
如果多个翻译单元(即“.c文件”)使用相同的数据类型、函数或变量,则相应的声明必须出现在每个翻译单元中。虽然程序员理论上可以直接将所有这些声明写入每个.c文件中,但这会使程序员很难更改声明,因为他们必须在每个.c文件中进行更改。因此,更容易的方法是为几个翻译单元制作一个公共的头文件,并使用C预处理器让各个独立的翻译单元#include头文件。
基于此,在您的第一个示例中所做的内容是“正确”的,因为它可以工作并且是有效的C代码。然而,这仍然没有意义,因为您正在为两个不相关的函数使用相同的声明。
即使函数具有相同的名称和原型,但它们仍然是互不相关的。这是因为这些函数具有内部链接(由于关键字static)。将不相关的函数共享相同的声明放在头文件中是没有意义的。例如,如果您决定修改一个函数的声明,您要如何在源代码中修改它?您不能修改头文件,因为这样您也会在所有其他翻译单元中修改具有该名称的其他函数。因此,将static函数声明存储在.c文件中而不是公共头文件中更有意义。

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