C语言 何时将静态函数定义放在 C 的头文件中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3956694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to put static function definitions in header files in C?
提问by horseyguy
I've come across some code that has a large static function in a header file and i'm just curious when it is/is not ok to do this. For example, if many .cfiles include the header, why not just define the function non-static and link it in ?
我遇到了一些在头文件中具有大型静态函数的代码,我很好奇什么时候可以/不可以这样做。例如,如果许多.c文件包含标题,为什么不定义非静态函数并将其链接到?
Any advice or rules of thumb on when/when not to put static function definitions in header files in C would be appreciated,
关于何时/何时不将静态函数定义放在 C 中的头文件中的任何建议或经验法则,将不胜感激,
thanks
谢谢
采纳答案by R.. GitHub STOP HELPING ICE
Some ideas:
一些想法:
- One possible legitimate use I can think of is when you want to make a function available without creating a symbol with external linkage and polluting the external namespace. (But then you could just use an obscure prefixed name like
mylib123__foobar, and#define foobar mylib123__foobarin the header file, so this one seems a little iffy.) - You want certain functionality to be available purely through the header file, without requiring the user to link a library/object files. I could see this being a real motivation when providing a 'library' that's almost nothing but data structures and a few trivial pieces of code to manipulate them. In fact if the data structures are not opaque and meant to be accessed directly by the application, putting functions for use with them in the same header file (versus in a library) greatly reduces the risk of breaking things if/when you change the data structures.
Perhaps the function is merely a wrapper for an external function, and the way the wrapper works might depend on compile-time options in the calling compilation unit. For example:
static int foobar(int x) { return real_foobar(COMPILETIME_PARAMETER, x); }You might say just use macros, but what if
foobarneeds to be called via a function pointer for the intended usage?
- 我能想到的一种可能的合法用途是,当您希望在不创建具有外部链接的符号并污染外部命名空间的情况下使函数可用时。(但是你可以在头文件中使用一个模糊的前缀名称,如
mylib123__foobar,#define foobar mylib123__foobar,所以这个看起来有点不确定。) - 您希望某些功能可以纯粹通过头文件使用,而不需要用户链接库/目标文件。当提供一个几乎没有数据结构和一些简单的代码来操作它们的“库”时,我可以看到这是一个真正的动机。事实上,如果数据结构不是不透明的并且旨在由应用程序直接访问,则将与它们一起使用的函数放在同一个头文件中(而不是在库中)大大降低了更改数据时破坏事物的风险结构。
也许函数只是外部函数的包装器,包装器的工作方式可能取决于调用编译单元中的编译时选项。例如:
static int foobar(int x) { return real_foobar(COMPILETIME_PARAMETER, x); }您可能会说只使用宏,但是如果
foobar需要通过函数指针调用以实现预期用途怎么办?
With that having been said...
话虽如此...
In reality, the main reason people put staticfunctions in header files is usually based on some 10-years-outdated notion that it will improve performance, by permitting the compiler to inline the function or whatnot. Most people who do this have not done any measurement. Since modern compilers can compile the whole program as a unit if asked, and this theoretically results in a lot more possibilities for optimization, and since it's a questionable optimization to begin with, I'm really skeptical of placement of functions in headers for performance purposes.
实际上,人们将static函数放在头文件中的主要原因通常是基于一些 10 年过时的概念,即通过允许编译器内联函数或诸如此类来提高性能。大多数这样做的人没有做过任何测量。由于现代编译器可以根据要求将整个程序编译为一个单元,这在理论上会导致更多的优化可能性,而且由于这是一个有问题的优化开始,我真的很怀疑出于性能目的在头文件中放置函数.
This criticism especially applies the OP's example of "large" static functions in header files. There's almost no way a large function could benefit from inlining unless a constant argument value allows the compiler to eliminate 90% of the code or something. (For a real-world example of this extreme case, see some of the crazy inline function/macro definitions used in libavcodec. :-)
这种批评尤其适用于头文件中“大”静态函数的 OP 示例。除非常量参数值允许编译器消除 90% 的代码或其他内容,否则大型函数几乎无法从内联中受益。(有关这种极端情况的真实示例,请参阅 . 中使用的一些疯狂的内联函数/宏定义libavcodec。:-)
回答by Jander
As a rule of thumb, you should not be putting static functions in header files. In a one-off program, it probably won't hurt anything, aside from expanding the size of your code because you've got a redundant copy in each module. In a shared library, it could easily cause bugs because now part of your library is embedded in the library's callers, so version mismatches could easily happen.
根据经验,您不应该将静态函数放在头文件中。在一次性程序中,除了扩展代码的大小之外,它可能不会有任何伤害,因为您在每个模块中都有一个冗余副本。在共享库中,它很容易导致错误,因为现在您的库的一部分嵌入在库的调用方中,因此很容易发生版本不匹配。
If you've got some terribly, horribly time-critical function where the time spent making the function call matters, you might consider putting it in the header, but in that case (a) you probably want to declare it inline as well, and (b) you've already done all the other optimizations you can find.
如果您有一些非常、非常时间关键的函数,其中花费的时间进行函数调用很重要,您可能会考虑将其放在标题中,但在这种情况下 (a) 您可能还想将其声明为内联,并且(b) 您已经完成了您能找到的所有其他优化。
In short, unless you know beyond the shadow of a doubt that you need your static function in a header file... you don't want a static function in a header file; you want a non-static function in a .c file with its header in the .h.
简而言之,除非您毫无疑问地知道您需要在头文件中使用静态函数……否则您不希望在头文件中使用静态函数;您需要 .c 文件中的非静态函数,其标头位于 .h 中。
回答by tobyodavies
In my experience it is generally a bad idea to definea function in a .h file, and i've never had cause to do so, doing so by accident once caused me no end of headaches.
根据我的经验,在 .h 文件中定义函数通常是一个坏主意,而且我从来没有理由这样做,一次偶然地这样做让我头疼不已。
Though i guess it would allow each file that includes the header to have its own separateimplementation of the function which, if the function has static vars, may be the desired behaviour e.g. if you want/need to keep track of some information separately for each file.
虽然我猜它会允许包含标题的每个文件都有自己单独的函数实现,如果函数具有静态变量,则可能是所需的行为,例如,如果您想要/需要分别跟踪每个文件的某些信息文件。
回答by Jens Gustedt
Modern C has adopted the inlinekeyword from C++ for such a task. But if your compiler doesn't have that (yet?) staticin header files is a way to emulate that. inlinedoesn't mean that the function is necessarily inlined to any caller but just that there will be usually at most one copy in the final executable. (Technically the corresponding linker symbols are "weak" symbols.) In contrast, if just declared staticevery compilation unit will keep a copy.
现代 C 已经采用了inlineC++ 中的关键字来完成这样的任务。但是如果你的编译器static在头文件中没有(还没有?)是一种模拟它的方法。inline并不意味着该函数必须内联到任何调用者,而只是在最终的可执行文件中通常最多只有一个副本。(从技术上讲,相应的链接器符号是“弱”符号。)相反,如果只是声明static每个编译单元将保留一个副本。
Such an approach of having function definitions in headers should be restricted to smallfunctions that do small tasks for which your compiler may improve the code substantially if it is optimized into the calling function.
这种在头文件中定义函数的方法应该仅限于执行小任务的小函数,如果将代码优化到调用函数中,编译器可能会大幅改进代码。
When doing so, be also careful with the implementation of these functions. You may break your possibility to include declarations into C++ by that. Generally the two languages only agree (mostly) on interfaces, not necessarily for the implementation, there are subtle differences.
这样做时,还要注意这些功能的实现。您可能会因此而打破将声明包含到 C++ 中的可能性。通常这两种语言只(大部分)在接口上达成一致,不一定在实现上达成一致,存在细微差别。
回答by Eric Towers
Can also be useful to define functions with static work buffers to be local to each translation unit. A particular example is strtok(). strtok() marches through a buffer one token per call. If strtok() calls are interleaved from two different places (i.e. two different translation units) then the results are not what is expected/desired. If each translation unit had its own copy of strtok() and therefore each translation unit had its own strtok() static variables, then this kind of stomping on the internal state would go away. If state stomping is happening, then both (sets of) calls are in the same translation unit and the debugging has some semblance of locality.
也可用于将具有静态工作缓冲区的函数定义为每个翻译单元的本地函数。一个特殊的例子是 strtok()。strtok() 每次调用通过缓冲区一个标记。如果 strtok() 调用从两个不同的地方(即两个不同的翻译单元)交错,则结果不是预期/期望的。如果每个翻译单元都有自己的 strtok() 副本,因此每个翻译单元都有自己的 strtok() 静态变量,那么这种对内部状态的践踏就会消失。如果状态践踏正在发生,那么两个(组)调用都在同一个翻译单元中,并且调试具有某种局部性。
(Note that the "correct" solution is to replace strtok() with a stateless function and make the callers responsible for holding context and state information, the same way fopen() and friends make the caller hold a FILE for each context.)
(请注意,“正确”的解决方案是用无状态函数替换 strtok() 并使调用者负责保存上下文和状态信息,就像 fopen() 和朋友使调用者为每个上下文保存一个 FILE 一样。)
回答by Andy Lester
If the function has external linkage, it should be declared in a .h file.
如果函数具有外部链接,则应在 .h 文件中声明。
If the function is static, and therefore has no external linkage, the function should only be declared in the .c file in which it is defined.
如果函数是静态的,因此没有外部链接,则只能在定义它的 .c 文件中声明该函数。
It is never OK to have a function defined in a header file.
在头文件中定义函数是绝对不行的。

