当我根本无法将其放在头文件中时,为什么要声明一个“私有”函数为静态?

时间:2019-04-05 14:26:07

标签: c header-files private

我了解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文件中简单声明它有技术优势?

3 个答案:

答案 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声明放在单独的头文件中,并且您的库的客户端只需包含具有公共功能的头文件即可。