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