C/C++: Static Function in Header File, What Does It Mean

Static functions declared in C header files

First I'd like to clarify my understanding of the situation you describe: The header contains (only) a static function declaration while the C file contains the definition, i.e. the function's source code. For example

some.h:

static void f();
// potentially more declarations

some.c:

#include "some.h"
static void f() { printf("Hello world\n"); }
// more code, some of it potentially using f()

If this is the situation you describe, I take issue with your remark

Since static functions have internal linkage we need to define it in every file we include the header file where the function is declared.

If you declare the function but do not use it in a given translation unit, I don't think you have to define it. gcc accepts that with a warning; the standard does not seem to forbid it, unless I missed something. This may be important in your scenario because translation units which do not use the function but include the header with its declaration don't have to provide an unused definition.


Now let's examine the questions:

  • What is the problem of declaring static functions in header files?
    It is somewhat unusual. Typically, static functions are functions needed in only one file. They are declared static to make that explicit by limiting their visibility. Declaring them in a header therefore is somewhat antithetical. If the function is indeed used in multiple files with identical definitions it should be made external, with a single definition. If only one translation unit actually uses it, the declaration does not belong in a header.

    One possible scenario therefore is to ensure a uniform function signature for different implementations in the respective translation units. The common header leads to a compile time error for different return types in C (and C++); different parameter types would cause a compile time error only in C (but not in C++' because of function overloading).
  • What are the risks?

    I do not see risks in your scenario. (As opposed to also including the function definition in a header which may violate the encapsulation principle.)
  • What the impact in compilation time?

    A function declaration is small and its complexity is low, so the overhead of having additional function declarations in a header is likely negligible. But if you create and include an additional header for the declaration in many translation units the file handling overhead can be significant (i.e. the compiler idles a lot while it waits for the header I/O)
  • Is there any risk in runtime?
    I cannot see any.

C/C++: Static function in header file, what does it mean?

Is the function defined in the header file? So that the actual code is given directly in the function, like this:

static int addTwo(int x)
{
return x + 2;
}

Then that's just a way of providing a useful function to many different C files. Each C file that includes the header will get its own definition that it can call. This of course wastes memory, and is (in my opinion) a quite ugly thing to be doing, since having executable code in a header is generally not a good idea.

Remember that #include:ing a header basically just pastes the contents of the header (and any other headers included by it) into the C file as seen by the compiler. The compiler never knows that the one particular function definition came from a header file.

UPDATE: In many cases, it's actually a good idea to do something like the above, and I realize my answer sounds very black-and-white about this which is kind of oversimplifying things a bit. For instance, code that models (or just uses) intrinsic functions can be expressed like the above, and with an explicit inline keyword even:

static inline int addTwo(int *x)
{
__add_two_superquickly(x);
}

Here, the __add_two_superquickly() function is a fictional intrinsic, and since we want the entire function to basically compile down to a single instruction, we really want it to be inlined. Still, the above is cleaner than using a macro.

The advantage over just using the intrinsic directly is of course that wrapping it in another layer of abstraction makes it possible to build the code on compilers lacking that particular intrinsic, by providing an alternate implementation and picking the right one depending on which compiler is being used.

When to put static function definitions in header files in C?

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

Using static vs not including function in header in C

When we have an application written by multiple people, and one person defined a function square to compute the mathematical square of a number and another person defined a function square to draw a square on a display, then, if neither function is defined with static, linking the program may result in a multiple-definition error. When the functions are defined with static, this multiple-definition error will not occur, because the same name will not be exported from multiple object files.

If there is only one definition of the name in the entire program, then no such multiple-definition error should occur. However, if the function is declared static, the compiler knows it does not have to export a definition. This means that, if the compiler “inlines” the function into all the locations that call it, it does not have to emit assembly code for a separate implementation of the function. (Inlining a function is the process of incorporating its code into the place where it is called, instead of using a call instruction to call the function.)

Static functions in header files in C++

When you include a header, the preprocessor will replace #include directive with the file contents. After that, all rules of static apply. That is, if you include a header with static functions into some compilation units (.cpp files), each compilation unit will get its own private copy of these static functions that will be accessible only from that compilation unit.

What's the difference between declaring a function static and not including it in a header?

The difference is that with a non-static function it can still be declared in some other translation unit (header files are irrelevant to this point) and called. A static function is simply not visible from any other translation unit.

It is even legal to declare a function inside another function:

foo.c:
void foo()
{
void bar();
bar();
}

bar.c:
void bar()
{ ... }


Related Topics



Leave a reply



Submit