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

6

61

I know what it means when static function is declared in source file. I am reading some code, found that static function in header files could be invoke in other files.

Krimmer answered 23/4, 2009 at 7:59 Comment(0)
T
84

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.

Toronto answered 23/4, 2009 at 8:0 Comment(4)
Well, the compiler will probably inline short functions. So it could actually use less memory, if the function is short enough. But I would prepend an "inline", so you don't get compile warnings about unused static functions.Tomasine
@Tomasine Good point, I've edited. Better late, I hope. :) Thanks.Toronto
I wonder if the linker will optimize that out. It sees addTwo on b.obj not being referenced then it removes the definition from the obj? If so, the overhead is just the (size of the function)*(number of different obj files that reference it). Still bigger than (size of the function), but not as bad?Gershwin
@jheriko Since each C file that includes the header will get its own local function, the code in the function will be repeated many times. Compared to having a single shared definition which is called by many users, that wastes memory.Toronto
A
21

It will effectively create a separate static function with the same name inside every cpp file it is included into. The same applies to global variables.

Athodyd answered 23/4, 2009 at 8:0 Comment(0)
B
12

As others are saying, it has exactly the same meaning as a static function in the .c file itself. This is because there is no semantic difference between .c and .h files; there is only the compilation unit made up of the file actually passed to the compiler (usually named .c) with the contents of any and all files named in #include lines (usually named .h) inserted into the stream as they are seen by the preprocessor.

The convention that the C source is in a file named .c and public declarations are in files named .h is only a convention. But it is generally a good one. Under that convention, the only things that should appear in .h files are declarations so that you generally avoid having the same symbol defined more than once in a single program.

In this particular case, the static keyword makes the symbol be private to the module, so there isn't a multiple-definition conflict waiting to cause trouble. So in that one sense, it is safe to do. But in the absence of a guarantee that the function would be inlined, you take the risk that the function would be instantiated in every module that happened to #include that header file which at best is a waste of memory in the code segment.

I am not certain of what use cases would justify doing this at all in a generally available public header.

If the .h file is generated code and only included in a single .c file, then I would personally name the file something other than .h to emphasize that it isn't actually a public header at all. For example, a utility that converts a binary file into an initialized variable definition might write a file that is intended to be used via #include and could very well contain a static declaration of the variable, and possibly even static definitions of accessor or other related utility functions.

Bearded answered 23/4, 2009 at 20:36 Comment(7)
Perhaps the function contains static variables that preserve their value between calls (internal state), and thus each module gets "its own private copy" of the vars by having its own clone of the function?Hopkins
@ranReloaded, That is a possibility. I'd personally avoid it because it would provide too many chances for a clever optimizer (or code maintainer) to break it by "cleverly" eliminating the apparently redundant function bodies. Also, it provides exactly one set of internal state per translation unit. It would be less confusing and less fragile to put all of the state in an explicit state variable, passed in to each call.Bearded
Yeah, I don't agree with that 'design' either. I would rather encapsulate private data in file-global static vars (C) or class members (C++)Hopkins
Although the pro is that the private data is encapsulated, visible right where needed and nowhere else.Hopkins
One use case of using static functions in a header file is to prevent getting a redefinition error when the same header file is included more than once from different compilation units. If the functions are not `static, you get a redefinition error at link time when the object files are turned into an elf. Note that if the header file is included more than once in the same compilation unit, you still get the redefinition error.Thaothapa
Another use case of using static functions is when you want to define stub functions and use macros to use the real function or the stub function in different compile scenarios. When the real function is used, you just use the function's prototype without the static keyword, but when the stub function is to be used, you include the function's body in the header file, in addition to adding static inline to it. This way, you do not need to define the stub function in the C file and you save space. You also do not get a redefinition error when the header file is included in test files.Thaothapa
This is an example of my comment above for the use case of static functions. #ifdef REGULAR_RUN bool foo(int bar); #else static inline bool foo(int bar) { return true; } #endifThaothapa
R
12

If you define the function in a header file (not simply declare it), a copy of the function will be generated in each translation unit (basically in each cpp file which includes this header).

This may increase the size of your executable, but this may be negligible if the function is small. The advantage is that the most compilers may inline the function, which may increase the code performance.

But there may be a big difference in doing this which wasn't mentioned in any answer. If your function uses a static local variable such as:

static int counter()
{
    static int ctr = 0;
    return ctr++;
}

Rather than:

//header
int counter();

//source
int counter()
{
    static int ctr = 0;
    return ctr++;
}

Then each source file including this header will have its own counter. If the function is declared inside the header, and defined in a source file, then the counter will be shared across your whole program.

So saying that the only difference will be performance and code size is wrong.

Randazzo answered 5/4, 2017 at 8:21 Comment(0)
E
1

There is not semantic difference in defining in source file or header file, basically both means the same in plain C when using static keyword that, you are limiting the scope.

However, there is a problem in writing this in header file, this is because every time you include the header in a source file you'll have a copy of the function with same implementation which is much similar to have a normal function defined in header file. By adding the definition in header you are not achieving the what the static function is meant for.

Therefore, I suggest you should have your implementation only in your source file and not in header.

Emalee answered 22/7, 2009 at 7:48 Comment(1)
There is a strong semantic difference if the function contains a static local variable. In one case, the static variable will be shared, in the other case there will be multiple different static variables for each compilation unit. Therefore the function behavior may be totally different.Randazzo
B
1

It is usefull in some "header-only" libraries with small inline functions. In a such case you always want to make a copy of the function so this is not a bad pattern. However, this gives you an easy way to insert separate interface and implementation parts in the single header file:

// header.h

// interface part (for user?!)
static inline float av(float a, float b);

// implementation part (for developer)
static inline float av(float a, float b)
{
    return (a+b)/2.f;
}

Apple vector math library in GLK framework uses such constuction (e.g. GLKMatrix4.h).

Bendite answered 16/7, 2012 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.