我发现了在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)
{
...
}
这两种使用静态函数的方法中哪一种是正确的?
答案 0 :(得分:4)
这两种使用静态函数的方法中哪一种是正确的?
第二种方法是正确的。
static void afunc(void);
是一个函数声明。该函数的定义存在于某处。由于它也是 static ,因此如果在此编译中使用该函数,则其定义也需要在此单元的此编译中。该功能具有本地链接。
在第二种情况下,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"
声明并定义一个小助手函数,目的是使包含"*.c"
的{{1}}都将获得其自己的{ {1}}。通过使其"afile.h"
,这些本地afunc()
不会与潜在的全局static
或彼此冲突。
答案 1 :(得分:2)
拥有头文件的要点如下:
如果多个translation units(即“ .c
文件”)使用相同的数据类型,函数或变量,则相应的声明必须出现在每个翻译单元中。尽管理论上程序员可以直接将所有这些声明写到每个.c
文件中,但这将使程序员很难更改声明,因为在每个.c
文件中都必须更改它们。因此,仅为多个翻译单元制作一个通用的头文件,并使用C preprocessor将各个翻译单元#include
制作为头文件会更容易。
基于此,您将在第一个示例中执行的操作在某种意义上是“正确的”,因为它将起作用并且它是有效的C代码。但是,它仍然没有意义,因为您对两个不相关的函数使用了相同的声明。
即使这些功能具有相同的名称和prototype,这些功能仍然彼此无关。这是因为函数具有internal linkage(由于关键字static
)。
不相关的函数在头文件中共享相同的声明是没有意义的。例如,如果您决定修改一个函数的声明,那么如何在源代码中对其进行修改?您无法修改头文件,因为那样的话,您还将在所有其他翻译单元中使用该名称修改其他函数。
因此,将static
函数声明存储在.c
文件中而不是公共头文件中更有意义。