Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static inline functions in a header file

Tags:

Lately I have been making an attempt to read more open source C code. A common pattern that I have been adopting in my hobby projects is as follows.

In my C files, I have functions that are either static or exported. Only functions that are exported are placed in a header file. Global variables which are only used within the scope of an object are also used as static global variables.

My question concerns the usefulness and motivation of having static inline functions inside header files. From what I read online, not using the static keyword causes a multiple definition error and that is the reason for not just defining the function as just inline.

However, does this mean that this function is exported for other objects to use? If yes, then why not just defining this function in the C file and export it via the header file? If not, why putting this in the header file rather than just having it inside the C file?

Is there a reason behind this coding style? What am I missing?

One such example can be found in the git codebase inside hashmap.h:

/*  * Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code  * for use in hash tables. Cryptographic hashes are supposed to have  * uniform distribution, so in contrast to `memhash()`, this just copies  * the first `sizeof(int)` bytes without shuffling any bits. Note that  * the results will be different on big-endian and little-endian  * platforms, so they should not be stored or transferred over the net.  */ static inline unsigned int sha1hash(const unsigned char *sha1) {     /*      * Equivalent to 'return *(unsigned int *)sha1;', but safe on      * platforms that don't support unaligned reads.      */     unsigned int hash;     memcpy(&hash, sha1, sizeof(hash));     return hash; } 
like image 367
learnlearnlearn Avatar asked Dec 14 '17 18:12

learnlearnlearn


People also ask

Can static functions be declared in a header file?

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.

Can inline functions be defined in the header?

You can have an inline implementation of a member function and you can put inline function definitions in a header file, it's just it might not be a good idea.

Can inline function be static?

Any function, with the exception of main , can be declared or defined as inline with the inline function specifier. Static local variables are not allowed to be defined within the body of an inline function. C++ functions implemented inside of a class declaration are automatically defined inline.

What is the use of static inline?

Static inline functions are simple. Either a function defined with the inline function specifier is inlined at a reference, or a call is made to the actual function. The compiler can choose which to do at each reference. The compiler decides if it is profitable to inline at -xO3 and above.


1 Answers

A static inline function is, in practice, likely (but not certain) to be inlined by some good optimizing compiler (e.g. by GCC when it is given -O2) at most of its call sites.

It is defined in a header file, because it then could be inlined at most call sites (perhaps all of them). If it was just declared (and simply "exported") the inlining is unlikely to happen (except if you compile and link with link-time optimizations, a.k.a. LTO, also, e.g. compile and link with gcc -flto -O2, and that increases a lot the build time).

In practice, the compiler needs to know the body of a function to be able to inline it. So a suitable place is to define it in some common header file (otherwise, it could be inlined only in the same translation unit defining it, unless you enable LTO), so that every translation unit would know the body of that inlinable function.

It is declared static to avoid multiple definitions (at link time) in case the compiler did not inline it (e.g. when you use its address).

In practice, in C99 or C11 code (except with LTO, which I rarely use), I would always put the short functions I want to be inlined as static inline definitions in common header files.

Be sure to understand how and when the C preprocessor works. Notice that you could in principle (but it would be very bad practice and disgusting style) avoid defining some static inline function in a common header file and instead copy and paste its identical definition in multiple .c files. (However, that might make sense for generated .c files, e.g. if you design a compiler emitting C code).

FYI LTO is practically implemented by recent GCC compilers by embedding some internal compiler representation (some GIMPLE) inside object files, and redoing some "compilation" step - using the lto1 frontend - at "link" time. In practice, the entire program is almost compiled "twice".

(actually, I always wondered why the C standardization committee did not decide instead that all explicitly inline functions are static)

like image 102
Basile Starynkevitch Avatar answered Nov 04 '22 00:11

Basile Starynkevitch