embedded software boot camp

Do Inline Function Bodies Belong in C Header Files?

Monday, March 21st, 2011 by Michael Barr

Earlier today I received the following question by e-mail from Brazil:

I am trying to conform to the rules in your Embedded C Coding Standard book and I just ran into what may be a problem with Rule 6.3.a. Instead of using function-like macros, I’m using inline functions, as you recommend. However, my compiler (avr-gcc) gives an error when I declare a function to be inline at both header and source file. If I put both the inline declaration and function body inside the header file it works fine. This fixes my compiler problem, but isn’t it a bad practice to place code inside the header file?

This is a good question, as it seems at first to be about a conflict between the Embedded C Coding Standard and what I refer to as “Generally Accepted Programming Principles” (i.e., GAPP not GAAP). It’s also approaching a frequently asked question, so I thought it’d also be good to share my e-mailed answer here.

The inline keyword is a part of the C++ programming language that was added late to C (in C99). In C++, most programs are built out of classes–with best practice dictating one header file per class definition. Any C++ function may be declared inline. But if the inline function is a public member function (a.k.a., public method) of the class it is necessary to place the code for the inline function inside the header file. This is so that all of the other modules that use the class can see the code they need to have placed inline by the compiler.

Of course, placing the body of any function inside a header file conflicts with GAPP for the C programming language. Here’s how you should decide what to do:

IF the inline function is a “helper” function that’s only used inside one C module, THEN put it in that .c file only and don’t mention it in the header file. This is consistent with Rule 4.2.c, which says that “The header file shall identify only the [functions] … about which it is strictly necessary for other modules to know.”

IF, however, the inline function operates on the abstract data type defined in the header file and must be visible to two or more modules, THEN put the body of the inline function inside the header file. There is no rule in the Embedded C Coding Standard that strictly prohibits this, so there is no conflict.

See my earlier post What Belongs in a C .h Header File? for additional suggestions concerning header file contents.

Tags: ,

10 Responses to “Do Inline Function Bodies Belong in C Header Files?”

  1. Nilton says:

    Very nice answer. Actually it’s a recurrent question from the students on the course I teach embedded programming. Specially when most of the students and me, I must admit, had the bad habit of filling the code with macros, when inlining is a much more elegant and safe resource.

  2. Lundin says:

    I completely agree that function-like macros should be banned, and functions should be used instead, that’s an excellent rule, which is sadly not adopted by MISRA-C yet, they have it as an advisory rule only.

    However… when people try to inline / function-like macro for the sake of speed, they are typically doing obfuscate-my-code-to-oblivion-to-win-one-pointless-CPU-tick optimizations in 99% of the cases. I work solely with “hard” realtime embedded systems, and in the past 10 years I can perhaps come up with one or two rare cases that actually -needed- to have the code inlined because of realtime considerations. In 99% of the cases, function calling overhead is a non-issue.

    If you -do- come up with such a rare scenario, you are writing some extremely performance-critical algorithm. Then all good coding practice be damned – make it happen. And if you do encounter such a situation, you should probably consider assembler instead of C anyhow, for that particular sensitive piece of code.

    And it seems even less likely that such a sensitive function ever needs to be exposed to the global scope / public, so the h-file issue seems like something you would never actually encounter in the real world. Assuming your program design is somewhat decent.

    Also note that the compiler may inline for you with or without keyword: inline is just a hint to the compiler, it may very well inline your code anyway, with optimizations for speed enabled (and optimizations for code size reduced).

  3. Frank says:

    This came up about ten years ago where I worked at the time. Rather than hide code in a header file we came up with the file extension “.inl”. This way anybody who sees it knows that there is code inside. The file extension was well documented in our coding guidelines so that any new developer to the company didn’t have to guess what a .inl file was.

  4. salmanza says:

    This is a very nice topic and I think very sensitive when talking about embedded programming specially in C language.

    I agree to all the answers and comments. In my experience as an embedded MCU software engineer I have seen several variants of inline function definitions. They are a very good alternative to function-like macros, however I have observed different effects and they are related to compiler capabilities. Sometimes, compilers inline functions by using the #pragma directive; this is not good if you want to reuse your code later. I remember another situation where inline functions were declared in a header file and this header file was included in a “global” header file which was included in several source files. The result was a significant memory overhead even in those files that did not use the inline functions, so to avoid waste a lot of Kbytes of memory we decided to move those functions to a C source and then declared as public; speed was not a problem for us but memory was (it was a 32-bit RISC MCU). The same code did not work well for a different MCU (8-bit)/compiler combination so changing the functions from inline to global functions was a good solution in that time.

    Depending on the compiler is being used, sometime you can enable the option of in-lining functions, not sure what the criteria of the compiler is when deciding which function may be converted to inline, so for speed optimization this seems to be a good alternative.

    After all, when compiler allows function inline keyword I prefer to use inline functions when I have to do SFR configuration. Usually this is small code and sometime you want to be fast, for example, when changing clock frequency during power management strategy and moving through different power domains. So I often use inline functions in the software driver layer for MCU configuration purposes and public APIs at higher layers; I’m not suggesting this is the best practice but just a personal preference.

    • Lundin says:

      SFR as in 8051? I suppose that may be yet another valid case where you must use inlining: when dealing with an unbelievably inefficient CPU.

  5. Rick says:

    New compiler platforms like LLVM (and clang, the C-language family front end) are able to do link-time optimization. LLVM can inline code across translation units, without seeing the inline declaration during translation. It does this using its best judgement, which is almost always better than the developer’s.


    Rick

  6. Daryl says:

    I would love to use LLVM and Clang for embedded development on AVR32’s. However besides not being available yet for AVR32 I noticed that it does not fully support C++, is this correct? I need a compiler that is good at C++ and for now i use gcc which is terribly inefficient in compile and is pretty poor at optimizations but considerably reliable.

  7. Juan Cazares says:

    I am writing code for a cortex M4 and the idea to use inline functions in my C code is avoid sharing global variables to other *.c files. Your suggestion is to write the body in the *.h file. The problem with this is that any global variable used inside the inlined function must be declared as extern in the *.h file. That’s exactly what I am trying to avoid.

    Any suggestion?

  8. Ashleigh says:

    In 15 years of writing embedded code, I don’t think I have ever a case where a piece of code HAD to be inlined across compilation units. To me this represents poor design / code smell, or using a processor so underpowered for the task that inlining is the only way to meet some performance target.

    I’d strongly suggest avoiding any form of inline and code in (plain C) headers, ever. Whilst it may be necessary for C++, it leads to terrible habits in plain C.

    As for Juan, asking about avoiding sharing global variables across compilation units, my advice is this:

    Either:

    – Use global variables and let the linker manage the type compatibility issues that may arise. Sometimes global variables are a necessary evil (just think hard about using them or not).

    – Make a new code unit, and wrap your global / shared resource in there with getter / setting functions. This is a very C++ / OO way of doing things but it does provide a nice encapsulation. Obviously this won’t be inlining things… but see above… really you should be trying to avoid this.

  9. Yann says:

    It’s an old post, but since I have the same problem right now …

    I was wondering if the existence of -flto compilation flag, now available in gcc and clang, which allows inlining at linking stage, hence accross multiple units, means that this practice (function body into .h) is no longer necessary ?

Leave a Reply to Daryl