embedded software boot camp

What Belongs in a C .h Header File?

Wednesday, November 10th, 2010 by Michael Barr

What sorts of things should you (or should you not) put in a C language .h header file? When should you create a header file? And why?

When I talk to embedded C programmers about hardware interfacing in C or Netrino’s Embedded C Coding Standard, I often come to see that they lack basic skills and information about the C programming language. This is usually because we are mostly a gang of electrical engineers who are self-taught in C (and every other programming language we use).

When the subject of header files comes up, here’s my list of do’s and don’ts:

DO create one .h header file for each “module” of the system. A module may comprise one or more compilation units (e.g., .c or .asm source code files). But it should implement just one aspect of the system. Examples of well-chosen modules are: a device driver for an A/D converter; a communication protocol, such as FTP; and an alarm manager that is solely responsible for logging error conditions and alerting the user of the active errors.

DO include in the header file all of the function prototypes for the public interface of the module it describes. For example a header file adc.h might contain function prototypes for adc_init(), adc_select_input(), and adc_read().

DON’T include in the header file any other function or macro that may lie inside the module source code. It is desirable to hide these internal “helper” functions inside the implementation. If it’s not called from any other module, hide it! (If your module spans several compilation units that need to share a helper function, then create a separate header file just for this purpose.) Module A should only call Module B through the public interface defined in moduleb.h.

DON’T include any executable lines of code in a header file, including variable declarations. But note it is necessary to make an exception for the bodies of some inline functions.

DON’T expose any variable in a header file, as is too often done by way of the ‘extern’ keyword. Proper encapsulation of a module requires data hiding: any and all internal state data in private variables inside the .c source code files. Whenever possible these variables should also be declared with keyword ‘static’ to enlist the linker’s help in hiding them.

DON’T expose the internal format of any module-specific data structure passed to or returned from one or more of the module’s interface functions. That is to say there should be no “struct { … } foo;” code in any header file. If you do have a type you need to pass in and out of your module, so client modules can create instances of it, you can simply “typedef struct foo moduleb_type” in the header file. Client modules should never know, and this way cannot know, the internal format of the struct.

Though not really specific to embedded software development, I hope this advice on good C programming practices is useful to you. If it is please let me know and I will provide more C advice in future blog posts.

Tags: , , , ,

57 Responses to “What Belongs in a C .h Header File?”

  1. Lundin says:

    I fully agree with everything stated. All of this is usually referred to as object-oriented design A module with a well-defined access interface and private encapsulation, that’s what OO is all about.

    Some aditional advice regarding function prototypes:
    In the context of function declarations, static/extern keywords are C’s equivalents of the more well-known private/public keywords in other languages.

    Those functions in the .c file that don’t need to be exposed outside the module should be declared with the keyword static, making it impossible to call the function from outside the .c file:

    static void internal_func (void);

    To further emphasize which functions that are public and private, you could also use the extern keyword for function prototypes that are public:

    extern void adc_init (void);

    In fact, if you don’t write static nor extern in front of a function prototype, C will implicitly add an invisible extern in front of it.

  2. GroovyD says:

    ‘DON’T include any executable lines of code in a header file, including variable declarations.’

    dont you mean variable definitions? where would the declaration of a global variable go? i have yet to see a program (especially embedded) that doesn’t use them. granted generally globals is a bad idea.

    • Michael Barr says:

      Yes there is a difference between the declaration of a global variable (e.g., uint8_t g_counter = 0;) and an extern declaration of that variable (e.g., extern uint8_t g_counter;). But NO you shouldn’t put EITHER into any header file.

      • JiangRui says:

        But if we want to use g_counter in another file, we make an extern declaration of g_counter in that source file ?

        • SomeEmbeddedSWGuy says:

          Don’t use g_counter in another file!

          In another file, call a function defined in same file where static g_counter is defined, and this function should do whatever needs to be done, increment g_counter, reset g_counter, or whatever.

          You’ll do even better if you expose INTENTION (what is the story behind incrementing the counter, or reseting it, what is the end effect or goal that is accomplished) and not IMPLEMENTATION (see, we have this here counter, g_counter is its name, and it holds the count of …). Then you freed yourself to better the implementation without affecting the code which depends on that feature.

  3. A good, succinct, no-nonsense article, Michael. However, it didn’t address the important matter of comments – specifically usage comments, in the case of a header file.

    This omission prompted me to start blogging again myself. My musings are here:

    All feedback gratefully accepted.

    • Michael Barr says:

      Nice comment and follow-on blog post, Peter. I completely agree that comment blocks describing how to use the public API of a module belong in that module’s header file. Too bad the standard industry practice is to hide this type of comments in the implementation source file instead.

      • Iain says:

        Just wanted to thank you guys for this input. I’m a student revisiting C after an absence and trying to remember all those best practices I learned ages ago. This tip about comments makes a lot of sense, and it’s very useful. The above article was also pretty helpful in succinctly clarifying for me what should and should not go in a header. The book I’m currently using to refresh my memory tends to assume everything is written into one .c file because apparently if students see any kind of complexity, they go back in their burrow for another six weeks and spring is delayed.

        Thanks again!

  4. Glenn Scheibel says:

    “DON’T expose any variable in a header file”

    Boy, if I had a nickel…

    The sadness is that there are so many C developers in general (not just embedded) that don’t get this. When you don’t get this part and cannot properly decompose source code into modules, you end up with total spaghetti.

    This is the cruft that leads to disgusting stuff like this:

    #ifdef _FOO_C_
    #define EXTERN
    #define EXTERN extern

    • Michael Barr says:

      I hate that cruft! Never a good sign to find a #define EXTERN extern.

      • Philippe Meilleur says:


        What about using the following precompiler code:

        // in filename.h
        #ifdef FILENAME_C
        #define FILENAME_EXTERN
        #define FILENAME_EXTERN extern

        According that the extern keyword is globally unique in a project, to prototype the public function(s) only:

        FILENAME_EXTERN void public_function1(uint8_t arg1, uint16_t arg2, void * p_generic_arg3);

        In my opinion this method prevents the need to prototype locally in the c source file (duplicate). It has been seen in the past to change the type of some arguments in the c source file and its prototype during development, but not its extern declaration in the header file.

        Even if static analysis tools could see such errors, I believe the best is always to minimize the risks from the source by using good work methods.

        • Michael Barr says:


          According to the C standard “void public_function1(…)” is equivalent to “extern void public_function1(…)”. That is to say that wherever function prototypes appear they are assumed extern. Thus I believe the code above is a long-winded way of saying nothing. (This “extern by default” property of functions is why we seek to hide the prototypes for “helper” functions in the .C module–and also tag them “static”.)

          There is a simpler way to prevent “the need to prototype locally in the c source file (duplicate).” The simple rule is that any .C module should always #include the associated .h file. So, for example, “adc.c” should always #include “adc.h”. Here’s how we’ve worded that rule in Netrino’s Embedded C Coding Standard:

          Rule 4.3.c: Each source file shall always #include the header file of the same name (e.g., file adc.c should #include “adc.h”), to allow the compiler to confirm that each public function and its prototype match.

          Hope this helps.


          • David Brown says:

            I don’t agree with everything you write in this article, but I do agree with this. I have never been able to understand the “#define EXTERN extern” nonsense that some people seem to like.

            Either a function is local to the C file (e.g., adc.c) and it is declared “static”, or it is exported and there is an “extern void foo(void)” in the header file “adc.h” and “void foo(void) { .. }” in the implementation file. The implementation file “adc.c” always has #include “adc.h”.

            Such a rule is simple, clear and reliable, and compilers can check that implementations match the extern declarations.

          • smertrios says:

            Mike, I’m missing something here… when you say “void fn();” is equivalent to “extern void fn();” then what’s the point of using the “extern” keyword when applied to function prototypes? it seems you’re implying it makes no difference. is that correct?

    • David Brown says:

      If I had a nickel for every time someone said “don’t use global variables, use accessor functions” I’d be rich. Think about the difference between these two modules:

      extern int volume;

      #include “volume1.h”
      int volume = 0;

      extern int getVolume(void);
      extern void setVolume(int newVolume);

      #include “volume2.h”
      static int volume = 0;
      int getVolume(void) { return volume;}
      void setVolume(int newVolume) { volume = newVolume;}

      There are plenty of programmers who will swear blind that volume2 is the “right” solution, because it hides the global data. But does it /really/ hide anything? No, in fact the user has exactly the same access in the same way. It is just less convenient, less clear, and leads to bigger and slower code.

      It is perhaps easier, or at least more tempting, to abuse global variables than to abuse access functions. But in the end you are doing the same thing – you are communicating data into and out of a module. You need the same discipline, and the same understanding of the consequences and validity of using the interface, whether the interface is a global variable or an accessor function.

      People will often argue that by abstracting the access with a function, it is easier to change the code later. So what? If you want to change how the global variable is accessed, then change it. You should not be accessing that variable very often in the program anyway – if you /are/ accessing it a lot, then it’s an indication that your code structure and discipline is poor. And if you change the functionality of the accessor functions, you are probably going to need to check all the code that uses it anyway.

      I agree that too many global variables is a sign of a messy structure. But too many unnecessary extra functions just make it worse. Global data is one of C’s ways to implement interfaces between modules – it is a poor idea to dismiss it because of religious convictions.

      • Michael Barr says:

        As a general rule, if your API design includes accessor functions of the get/set variety you describe, then you are doing API design wrong. This cruft is all too common.

        But that doesn’t make data hiding altogether bad. There are good ways to design APIs around abstract data types too.

        • David Brown says:

          Oh, I agree with that – data hiding in general is a good idea. What I disagree with is /obsessive/ data hiding, especially when people treat something like “thou shalt not use global variables” as an unbreakable rule. If there is one thing that is constant in embedded development, it is that the answer is always “it depends”. It is good to hide the details of your implementation within the relevant modules, but only if the cost of doing so is not too high.

      • gallier2 says:

        I’m with David Brown here. Of course, the need of global variables should be held to a minimum, if a project is riddled with them, it’s difficult to scale the project. This said, if you have indeed a clear use for a global variables there’s no need to force stupid accessors. As example, in our project we have a clear need for lookup tables, which are constant, used in every sub module in a lot of sub projects and relatively big, declaring therefore a
        extern const wchar_t cp1252_unicode[MAX]; in the interface of the module is the simplest, fastest and cleanest way of implementing it.

        The evil of global variables comes when they are used to pass state between functions. A global variable is an information concerning the state of the application.

        • David Brown says:

          It is true that global variables can make a program difficult to scale, and they can make it difficult to re-use modules – it is harder to make a rigid and well-defined interface to a module when you have global variables.

          But this is embedded programming – for many programs, you are not interested in scaling. You know what the program has to do, and that is /all/ it has to do. If your program has to control the speed of an electric drill motor, then that is what it is doing – it doesn’t have to control two motors, or play music in the background. It’s okay to have state information such as “motorRunning” as global variables – as long as other modules use it safely. But that is no different from any other way of reading or changing state – functions such as “startMotor()” and “stopMotor()” must be used with the same care.

          When programs get bigger, and programming teams get bigger, you have to take more care to make your interfaces rigid and restricted, and to add greater checks on the usage of the interface – and global variables are not popular here (except with C++, where global object instances can be okay). But when programs are smaller, you aim for simple, clear and efficient interfaces, and global variables play a much bigger role.

          Regarding constant data, however, it is fine to make your consts global. In fact, it is very common to put small constants directly in the header files as “static const int sizeOfData = 123;”. It is as clear and safe as using a “extern const int sizeOfData;”.

      • Tod Gentille says:

        Re: “People will often argue that by abstracting the access with a function, it is easier to change the code later. So what? If you want to change how the global variable is accessed, then change it.”

        OK How? If I decide that my volume variable should now always be read from an external widget with accessors I just change the implementation of getVolume and I can be confident that all access to “volume” is updated. If I exposed a global variable I’m stuck. I have no control of how users of my framework/library/module are using that global variable. That’s why accessors are “generally” a good idea. Even if you’re the only one using your code they’re generally a good idea. Do you really want to package up reusable code into a library that exposes global data? If you need to optimize (and you probably don’t) you can inline the accessor code and it’s probably no less efficient or bloated than the global variable approach. It’s just safer and one heck of a lot easier to debug for the maintenance programmer that inherits your code. I’ve seen lots of hard-to-maintain code that uses global data, and not once has it been justified by performance or code-size issues, just laziness or ignorance. I’ve never cursed a programmer for making me use an accessor method. The commandment by the way is: “Thou shalt not use global data without a damn good reason that the maintenance programmer agrees with.”

      • Garry says:

        It is clear that volume1 and volume2 are NOT equivalent.

        The bulk of the objection to volume2’s using access functions seems to be “less convenient, less clear, and leads to bigger and slower code”. Is that a fair summary?

        If the syntax of updating ‘volume’ were were identical to using volume1 in the source code, would the ‘less convenient, less clear’ objections go away?
        If the speed and size difference could be eliminated by correct use of compiler flags, would those objections go away?

        Put another way, are all of those objections potentially soluble by careful use of a programming language like C++ or C#?

        Some of the issues comparing the two approaches are discussed, but some are not. If all of those objections go away, then IMHO we should consider the other side of the argument.

        The code to actually *update* volume in volume1 is in every part of the program that updates it, but the code to actually *update* volume in volume2 can be forced to exist at only one place. Depending on the development system, it may be possible to choose to distribute the update code to all the update sites using volum2 by changing a few compiler flags and/or a single piece of source code. So, not only are the two approaches functionally different, the scope to change the functional behaviour of the program during developmnt is different.

        This wasn’t discussed as a difference, and I think it can be important.

        A contrived example: If the debugging system does not support ‘data watchpoints’ but only a limited number of breakpoints, the difference may become extremely significant. An intermittent problem might be hard to find, and access functions may be better than direct data access. One approach might be to augment the code around the setting of volume to log a little bit of extra information to help diagnose the error. For example, the return address of the code attempting to update the variable is available (maybe in a link register, or on a stack). None of the other code would need to be changed, so the ‘Heisenberg effect’ of making code changes is likely more limited in the case of accessors than global data.

        I am putting the case that writing code which makes it easy to take a defensive approach, in the absence of other issues, is inherently worth considering as a ‘good thing’.

        I don’t accept the “you should just get yourself a better debugger and development system” response. That seems equivalent to saying, “make the world work in a different way, and you would have a solution to that development problem”. IMHO, it is a smaller problem to write robust code than make the world work in such a way that all development problems can be sidestepped.

        I have not seen any solid, evidence based, research that supports the view that access functions are inherently less clear than assignment. Maybe someone can direct me to it? I tend to think both sides of the debate are ‘religious war’ stuff in the absence of evidence.

        I am willing to suggest that the fact that there *is* an explicit difference between local variables and ‘globals’, where locals can be assigned directly, and all ‘global’ data must be ‘accessed’, might actually help.
        Of course, some programming languages allow that syntactic difference to be hidden, so that may be a mute point.

        I especially accept a concern over ‘lack of syntactic clarity’ is important, but that may depend on the language used. If ‘lack of syntactic clarity’ is the main objection, then it may also be an argument for some languages and against others.

        I am simply aiming to ensure a more complete set of issues are considered, and clarify the previous objections.

  5. Of course the biggest example of a public-domain C program, that is the Linux sources, seem to follow neither your rules, nor any other rhyme or reason.

    What I LIKE to see is the .h file imported into the .c fie so that the .h file provides function prototypes for the implementation. It’s a swine to implement that properly in C though.

    Or we can all learn to program in a language that works in modules, then learn C afterwards.

    • David, I don’t see what is difficult about including a header file in its related C file, so that the compiler can check for inconsistencies.

      Of course, it’s a swine to enforce!

      Sadly, it surprises me not at all that the Linux source coders paid little heed to such things.

      • kalpak dabir says:

        If something important is a swine to enforce, isn’t that is a flaw in the language design or implementation?

        Also, wouldn’t it be better if the definition was done in the .h file rather than write separate code again for global variable initialization?

        Ideally, that defined value will be a meaningful #define in the same .h file rather than a magic number.

        • Peter Bushell says:

          (a) If C required prototype function declarations for all functions defined in a file (not just called there), that would be a step in the right direction. However, it doesn’t. C is by no means flawless, I have to agree.

          (b) Again, I agree with your point, but in C you can/should put only the declarations in the .h file. More importantly, your question becomes academic if there are NO global variables. The real question for me is: “Why does C permit global variables?”. Note that I’m not including static variables in my definition of “global”, but these belong in the .c files anyway. I never define global variables in my code and “extern” has been expunged from my C vocabulary! Except, of course, when I have to work on some other people’s code and don’t have the opportunity to redesign it.

          (c) Academic (see (b)), but I don’t agree with you here, anyway. Although I never define global variables, I do sometimes define global constants – but only in C++ which (unlike C) has no problem with their being defined in header files. Having defined such a constant in a header file (near the top, of course), I see no reason to have a separate #define for its value, just a few lines away in the same file. Indeed, C++ treats constants the way it does in order to promote the usage of const instead of #define, in this context. However, this, being about C++, is off-topic…

    • David Brown says:

      Linux is not public domain. There is a vast difference between public domain code and open source code.

      There are also different reasons for having different styles of C programming, and different rules for how code is built up. Michael Barr, and presumably most of the readers of this site, are concerned with embedded C programming. These are typically programs consisting of a few dozen of modules with perhaps tens of thousands of code lines, with one or two programmers. Linux has many thousands of modules, millions of code lines, and thousands of developers scattered around the world. Complaining that Linux code is not organised like your own code is like saying that the books on your shelf are organized by height, because that looks neater, and then complaining when a library sorts them differently.

      Linux does have style guides, which are easily found by anyone who wants to read them. I certainly wouldn’t claim that all of the Linux code base follows all the rules, nor that they are the best rules for a project of that size. But the situation is not nearly as bad as you seem to think.

  6. dan says:

    Quick question. You wrote:

    DON’T expose the internal format of any module-specific data structure passed to or returned from one or more of the module’s interface functions. That is to say there should be no “struct { … } foo;” code in any header file. If you do have a type you need to pass in and out of your module, so client modules can create instances of it, you can simply “typedef struct foo moduleb_type” in the header file. Client modules should never know, and this way cannot know, the internal format of the struct.

    I didn’t quite understand the point here. It seems that if a structure (or more likely, a pointer to struct, whether it’s typedef’ed or not) is passed between client code & the library/module’s code, then the details of that struct have to be exposed.

    For example, let’s say I’m using a windowing library. If I make a call to an API function DrawWindow() as follows:

    void DrawWindow(Window const *foo);

    Window w;
    w.top = 55;
    w.left = 44;
    w.bottom = 66;
    w.right = 77;
    w.color = BLUE;

    Then the caller (client code) needs to know what a Window is. Whether it’s a “struct foo” or a “moduleb_type”, it doesn’t seem to matter.

    I wasn’t sure if the point was to use typedefs, or to hide details of structures – which isn’t always possible.


    • Michael Barr says:


      What you describe is an efficient interface, wherein the client directly manipulates the fields of the struct. But it’s not a true abstract data type or encapsulated interface.

      What about an alternative API such as:


      typedef struct window * window_handle;

      window_handle window_create(int top, int left, int bottom, int right, color_t color);
      void window_draw(window_handle);
      void window_destroy(window_handle)


      #include "window.h"

      window_handle my_window;

      my_window = window_create(55, 44, 66, 77, BLUE);


      • Eric Lariviere says:

        Hi Michael,

        If I understood correctly, your example assumes that window_create() and window_destroy() will manage the memory allocation of struct window instances. What if we did not want to rely on the window module to manage the memory allocated for these instances? Is there a way to hide the module-specific structure format in the header file while letting the application manage its own memory pool.

        For example:


        typedef struct window
        uint16_t top;
        uint16_t left;
        uint16_t bottom;
        uint16_t right;
        color_t color;

        } window_object;


        #include “window.h”

        window_object first_window;
        window_object second_window;

        window_create(&first_window, 55, 44, 66, 77, BLUE);
        window_create(&second_window, 11, 22, 33, 44, RED);

        In this example, window_create() would initialize the structure with arguments, but would not manage memory allocation. The compiler must know the size of window_object in order to declare first_window and second_window.

        Is it possible in this case to hide the elements of the window_object structure while having its size available within the application at compile time?



        • Sheldon says:

          I think I agree with Eric – I don’t want all of my modules to have to define their own pool of resources just so that we can avoid exposing the details of the structures. Then I could run into either over-allocating memory for each of the various files, or worse, under-allocating and not being able to easily detect the problem. I would hate to typedef my private structure to “char[18]” or something similar because then that just leads to nasty type-casting with potential bugs when the size of the structure isn’t maintained with the array size.

          Unit testing has also become more popular in recent years (embUnit does a pretty decent job). But either you expose more of your private methods through the header file(s) so that you can unit test them, or you duplicate prototypes and definitions within the unit test files so that you can test your routines. (Although I still prefer to only unit test the public interface anyway, some would argue that each routine should be individually unit-tested – and in that case, you have to expose your internal workings).

        • Tim says:

          Eric’s took the words right out of my mouth. I cannot seem to find a way to hide struct information and at the same time allow the application to own the data. It seems that either the module owns the data and assigns handles (as per my understanding of Mike’s example), or you expose the structure and allow the user to allocate data. In the latter case you just have to hope that the user only edits the structure using the module’s API.

          Are there really any other ways (aside from c++)?

          • David Brown says:

            There is no good way to hide the struct details while allowing a user to own the memory directly. Fundamentally, the compiler needs to know the size of the data struct in order to allocate the memory (whether it be on the heap, the stack, or statically). If you are perverse enough, you can do it by having the header file make typedefs that turn the struct into a block of memory of the right size and alignment, which can be made to work using a bit of horrible macros (including definitions that change depending on whether the header is being included from the implementation module or a different file).

            C++ does not help here – the situation is the same.

        • gallier2 says:

          I use that pattern a lot in my projects and it is quite useful. For some basic data types though it is a little painful (dynamic strings or some such), for bigger structs it’s really usefull. The only problem, as you have noted, is that the size of the structure is unknown outside of the module, which disallows compounding structures (I needed it once because of a shared memory object to communicate between tasks). I managed to solve the problem by declaring a method (or a global variable) returning the size of an object, so that the caller could allocate the needed size and the copy method of the module later populated the structure adequately.

      • David Brown says:

        That API implies using dynamic memory which should normally be avoided in embedded systems unless there is no better way.

        Using that style may also lead to bigger or slower code (because of the pointer indirection) and be harder to debug; this is not a popular strategy for embedded programming. When it also makes the source code clumsier and unclear, it’s time to question the “hide everything” policy.

        Putting struct definitions in a header will sometimes expose more implementation detail that you would like. That’s life with C programming – and it gets much worse with C++. You should try to keep such exposure to a minimum, and use comments (or “private” for C++, or possibly conventions such as identifiers ending in _, or even extra header files) to make it clear what is “public” information and what is “implementation” information. But if you get obsessive with information hiding, you make worse code in the end.

        • gallier2 says:

          By using that pattern it allows us to change libraries without recompiling the binaries that call them (granted I talk about shared libraries on a Unix system).

          • David Brown says:

            You are talking about a completely different sort of programming here, where you are aiming for re-usable libraries rather than compact and efficient embedded code. Then the rules are different, and a more abstract interface is essential. You need to be able to change either side of the interface (the implementation, or the usage) independently – that means a much more rigid and restricted interface, with layers of indirection and abstraction to allow flexibility. But when you are working with smaller systems, it’s okay to re-compile both sides of the interface if that gives you more efficient code.

          • gallier2 says:

            Granted, my example that I use actually is on a Unix system, but (and that you couldn’t know) I used the same scheme on a small embedded system before (Am186EM based programmable terminal with 512K of RAM and 512K of FlashROM) with good results. It’s in fact conceptually not much different than working with handles (be they unix stream like file handle or windows like HANDLE objects) except that the real pointer value is used as handle value. The client code could only use the object via the methods and the object implementation didn’t need to look up for the real address of the object, which always costs either place or time. One advantage this solution had over any other was that we could violate the encapsulation for debugging or test purposes.
            But as I said above, this kind of encapsulation was only worthwhile for somehow bigger structures, for simpler things like helper strings or else, it can be a bit too much overhead.

  7. Ewout Boks says:

    Good article Michael.

    I would like to add one remark : all your points are automatically taken care of when using C++. If you design your software around classed instead of C functions and variables, you can precisely lay-out what may and may not be exported from your code to other parts of the program. C++ will (at compile-time) check that everything conforms to your class design. All the problems mentioned here (including problems introduced in other comments) will be solved by using a C++ approach.

    I do not understand why C++ is not used much more in the embedded world. It is very effective, prevents a lot of errors, speeds up building large software projects, and the impact is minimal when used properly. If need arises, mixing with C code and Assembly is absolutely possible. I use it with a lot of satisfaction on my embedded (Cortex-M3) platform.

  8. Steve says:

    Hi Michael,

    I enjoyed the article, especially the follow up for the hiding of data structures by you and Eric Lariviere.

    I think that header files should also include some template stuff to
    a) be effective against being included multiple times
    b) be portable to C++

    #ifndef MODULE_NAME_H
    #define MODULE_NAME_H

    /* non-function code here: constants, etc.. */

    #ifdef __cplusplus
    extern “C” {
    #endif /* __cplusplus */

    /* interface function prototypes here */

    #ifdef __cplusplus
    #endif /* __cplusplus */

    Best Regards,


  9. Ralf Holly says:

    DON’T expose the internal format of any module-specific data structure passed to or returned from one or more of the module’s interface functions. […] Client modules should never know, and this way cannot know, the internal format of the struct.

    Sorry, but I didn’t get that one. Could you please clarify? How would you write this code?

    // employees.h

    typedef struct employee_t {
    int id;
    char* firstName;
    char* surname;
    double salary;
    struct employee_t* manager;
    } employee_t;

    bool LookupEmployee(int id, employee_t* emp);
    bool AddSubordinate(const employee_t* manager, employee_t* emp);

    • Michael Barr says:


      typedef struct employee_t * employee_t;

      bool LookupEmployee(int id, employee_t emp);
      bool AddSubordinate(const employee_t manager, employee_t emp);

      Put the struct’s internal details in employee.c, where the compiler can find them.

      • Ralf Holly says:

        I saw too late that there was already a comment about this: The downside is that you cannot control memory allocation.
        Small aside: ‘const employee_t manager’ makes the pointer const, not the pointed-to type, as in my example. So you would probably also need:
        typedef const struct employee_t* const_employee_t;
        Doesn’t look very nice, though…

        • Gauthier says:

          A couple of years ago I would have written it exactly as Michael. Nowadays after working in a Linux environment, I changed my mind. In Linux code, typdefing is often frowned upon as unnecessary hiding, certainly for `struct` and especially for pointers. The only case where it is accepted is for complex function pointers.

          I found it strange first but I complied, and now I think that `bool LookupEmployee(int id, employee_t emp);` looks very awkward. `emp` does not contain actual data. Nothing in the prototype shows that it actually is just a handle, or to what this handle would be.

          Further, the struct tag is no type, so the _t suffix is not appropriate there (some would also argue that you shouldn’t use _t on your own user-defined types, I have no opinion about that yet).

          As mentioned in other comments, this is the way to do OO in C, and as such I adopted the convention of always having the object handle first. C++’s `Instance.member_function(param)’` becomes in C `member_function(handle, param);`

          Put together, I would now write:


          struct emp; /* forward declaration, caller does not know about the content */
          bool employee_lookup(struct emp *emp, int id);
          bool employee_add_subordinate(struct emp *manager, const struct emp *emp);


          /* actual struct definition, hidden */
          struct emp {
          int id;
          char* firstName;
          char* surname;
          double salary;
          struct employee_t* manager;

          bool employee_lookup(struct emp *emp, int id)

          bool employee_add_subordinate(struct emp *manager, const struct emp *emp)

          Bonus: you get to place `const` wherever you want (note that in the function to add a subordinate, you probably don’t want *manager* to be a pointer to `const`).

  10. Hello Michael,
    I agree with you that “DON’T expose the internal format of any module-specific data structure passed to or returned from one or more of the module’s interface functions.” is a good practice, information hiding is a must also developing embedded applications. I think there are 2 exceptions to this rule:
    1. defining microcontroller’s register as a union whit inside a bit field and then placing it to a specific memory address using a define or a const pointer to the register address.
    2. defining a HAL to access similar pheriperals of different vendors. I work with Cortex Mx mcu of different vendors, all would implement ARM CMSIS common interface but in practice a timer module is obviously little different for every vendor. So, trying to design a common HAL API to make the C code independent from the particular timer is quite difficult using functions with parameters passed only by value. A solution is to pass a pointer to a struct/typedef struct (defined in the vendor specific .c file) with typedef struct x in the .h file; so the signatures of the HAL functions may be always the same for every vendor. Of course it is still possible to hide the struct internal details passing a void pointer instead of a pointer to a typedef and then cast to the correct type inside the functions.

  11. Deep Joshi says:

    How to use control and looping statements like if,for,while in a header file????

  12. Marcelo Jo says:

    Hi Michael! Great post as always!
    I’d like to know why we always need to hide the internal struct format? I mean, in the example of the window (above), why use the

    my_window = window_create(55, 44, 66, 77, BLUE);

    approach instead of

    window_create(&first_window, 55, 44, 66, 77, BLUE);

    In the first approach we could access all data with get/set functions like:
    and so on…

    Me personally use the second approach where I can set the variables in one shot or get the entire struct in one shot as well instead of several get, get, get, get…

    What should I do?

    Thank you very much

  13. […] Coding Standard. [6] BARR, Michael. “What Belongs in a C .h Header File?” available at https://embeddedgurus.com/barr-code/2010/11/what-belongs-in-a-c-h-header-file/ Like this:LikeBe the first to like […]

  14. Rob says:

    I would disagree with making a typdef of a structure. I hate typedefs, they make code much harder to read to my mind. I believe they are, in fact, banned in the Linux kernel.

    Also, I think it makes code *much* easier to read if the structures are declared in a header file, plus if different c files (and why wouldn’t they?) want to utilise the same structure, it makes it easier by doing a #include of the header file in which the structure is defined.

    Having dabbled a little in C++ the accessor function way of doing things in C does seem the same as C++ and a neat way of avoiding global variables. I have now got into the habit of using static variables within functions and manage to almost completely (other than for interrupt routines) do away with globals.

    Even better though, I have largely completely managed to avoid globals by using FreeRTOS a lot recently! Going back to writing run-to-complete code seems so passé now! ;~)

  15. stephen says:


    In the “Embedded C Coding Standard” rule 4.2d “No header file shall contain a #include statement. Can you elaborate the reasoning?

    If a function uses a parameter with bool or uintxx_t type, the header file defines its prototype has to include or . Does this violate the rule? If I want to compliant with the rule, what is the best approach?

  16. David Rankin says:

    It’s not only EE who are self-taught coders. Aeros are also notorious for it. For an excellent example of encapsulaton (along with dynamic linking/late binding to help accomplish the task) see: Object Oriented C (http://www.cs.rit.edu/~ats/books/ooc.pdf) An excellent read and challenge for all self-taught coders, but the “Ah-hah!” moment is worth it.

  17. […] article What Belongs in a C .h Header File? covers several points that I mostly agree […]

  18. […] concept of why header files are important is described here on http://www.cplusplus.com. Another good discussion and fast ‘howto’ is written here (read the discussion!). Also, a great […]

  19. Abderrezak says:

    Thank you Michael for this post and for the book (Embedded C Coding Standard).
    How can I deal with this rule “no header file should contain a #include statement”? Is there an exception? Why such a rule?
    In general, I guarantee that “interface.h” can be compiled by it self (main_test.c that do-nothing and include “interface.h”).

  20. […] concept of why header files are important is described here on http://www.cplusplus.com. Another good discussion and fast ‘howto’ is written here (read the discussion!). Also, a great […]

Leave a Reply