Writing good header files in C

Ajay Nair
3 min readMay 6, 2015

Writing correct header files are very important, especially in a multi-layered project. Most students never work on multi-layer projects in college and find it difficult initially to write the header file in the correct way.

Consider the following scenario

Module Boss has files:

boss.c boss.h

Module Manager has files:

manager.c manager.h

Module worker has files:

worker.c worker.h

Boss represents the boss of a company, Manager is a level below the Boss who looks after the worker. Worker is the person who does the actual work of say testing. In the real-world, Boss is not concerned with how the Manager gets the work done. The Boss only tells the Manager what work needs to be done. In other words, neither boss.c nor boss.h should have any code or data structure related to Worker in it.

//worker.h                                        //worker.c
#include <stdbool.h>
struct worker { #include <xml.h>
int name; int finished_work_count; int test1(...)
bool gender; ... {
}; ...
}
//manager.h //manager.c
struct manager { #include "worker.h"
int name; void *priv; ... int test(...)
{
}; ...
test1(...);test2(...);
}
//boss.h //boss.c
struct boss { #include "manager.h"
int work(...)
int name;... {
}; ...
code(...); test(...);
}

Note the following points:

  • #include <xml.h> is in worker.c and not in worker.h
  • #include “worker.h” is in manager.c and not in manager.h and similarly #include “manager.h” in boss.c
  • #include <stdbool.h> is in worker.h
  • struct manager has void *priv member

Let’s say worker module uses xml library in some of it’s functions. Then xml.h should be included in worker.c and not in worker.h. If you include xml.h in worker.h then manager.c which includes worker.h would unknowingly be including xml.h too even though it is not needed. Header files should contain as less declarations as possible. Keep in mind that header files are exposed to any layer which wants to use that module.

Note that stdbool is included in worker.h. Struct worker has a member ‘bool gender’, this compels us to include stdbool in the header file. The general rule to follow is to have as many #include ‘s as possible in .c file instead of .h file. Students often follow the exact opposite rule.

Layer 1 should never depend/talk with Layer 3 i.e. Boss should not have any relation with Worker. In struct worker there is a void *priv field. This field is to be used to store the pointer to struct worker. We are compelled to write void *priv instead of struct worker *w as a member of struct manager because struct worker is defined in worker.h and worker.h cannot be included in manager.h. If worker.h is included in manager.h and manager.h is included in boss.c (which is the case here) then boss.c is indirectly including worker.h which is a violation of the rule.

Writing a perfect header file saves a lot of time in debugging later. Creating the habit of writing perfect header files takes time so start early.

Originally published at http://care2code.wordpress.com on May 6, 2015.

--

--