views:

139

answers:

6

Hi,

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 .c files include the header, why not just define the function non-static and link it in ?

Any advice or rules of thumb on when/when not to put static function definitions in header files in C would be appreciated,

thanks

A: 

If the function has external linkage, it should be declared in a .h file.

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.

It is never OK to have a function defined in a header file.

Andy Lester
He is talking about _defining_ not declaring. that is the function's body is in the header
tobyodavies
I'm surprise that you are putting .h and .c file in single solution....
YeenFei
I don't agree with the "never OK" part. It might not be an ideal design, but there are reasons, as stated by tobyodavies.
Matthew Flaschen
+3  A: 

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.

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.

Jander
+3  A: 

In my experience it is generally a bad idea to define a 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.

Though i guess it would allow each file that includes the header to have its own separate implementation 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.

tobyodavies
I think your second paragraph is on the right track. I do agree that if you can make the function reentrant (e.g. by allocating then passing in a pointer to a state structure), that would be a much better solution.
Matthew Flaschen
+1  A: 

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.

(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.)

Eric Towers
+1  A: 

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__foobar in 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 foobar needs to be called via a function pointer for the intended usage?

With that having been said...

In reality, the main reason people put static functions 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.

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. :-)

R..
+1  A: 

Modern C has adopted the inline keyword from C++ for such a task. But if your compiler doesn't have that (yet?) static in header files is a way to emulate that. inline doesn'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 static every compilation unit will keep a copy.

Such an approach of having function definitions in headers should be restricted to small functions 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.

Jens Gustedt