我理解static
关键字用于创建对翻译单元(源文件)“私有”的函数或变量。
但是,据我所知,为了确保某个特定的函数或变量不能从声明它的.c
文件外部访问,我只能在相应的.h
文件中声明它。
例如:
F.C
void public_func() {
// ...
}
void private_func() {
// ...
}
f.h
void public_func();
// no declaration of private_func
那么我为什么还要将private_func
声明为static
?这只是一个惯例,还是仅仅在.h
文件中没有声明它有技术上的好处?
问题是编译器在“翻译单元”的基础上工作,这意味着一个.c文件和它包含的所有.h文件。因此传统上无法检测整个项目中的命名冲突。
因此,如果你没有使它成为static
,该函数默认为“外部链接”。意味着如果在同一个项目中有一个函数private_func
和另一个转换单元使用相同的名称,则在链接和链接器错误期间会出现命名空间冲突。
这也是一个正确的问题 - 私人职能/变量应该无法从外部访问,无论是有意还是无意。
我理解static关键字用于创建对翻译单元(源文件)“私有”的函数或变量。
确实如此。
这仅仅是一个约定,还是仅仅因为没有在.h文件中声明它而具有技术优势?
这里有一个技术问题。编译完成后,它会生成一个目标文件。该文件具有符号表,当链接器将程序从单独的目标文件放在一起时,链接器稍后使用该符号表。 static
函数不会进入该表,因此从其他目标文件直接引用该函数将失败,并在链接阶段出现“未解析的引用”错误。
Benefits
?那么你在对象文件中保存了一些小空间,链接阶段会更快,因为会有一个较小的表来处理。但这足够小,不会产生任何影响,除非我们谈论的是数千个具有loooong名称的函数的组合案例。
如果你有一个非static
函数,并且在头文件中省略了它的声明,那么函数名仍会进入符号表。如果我碰巧以某种方式知道声明(除了从头部开始),我仍然可以直接从另一个转换单元调用/引用该函数,不会发生链接器错误。
假设你写了一个由几个.c
和.h
文件组成的库。库的客户端需要使用一些头文件来使用您的库。他们应该只看到公共职能。
但是对于库的实现,您可能还使用头文件,因此库中的函数可以调用其他(内部)函数。
所以你最终得到两种类型的声明:
对于您图书馆的客户
void public_func();
供内部使用
static void private_func();
优选地,私有和公共声明位于单独的头文件中,并且库的客户端只需要包含具有公共函数的头文件。