This is how I do it:
naeem1234How to expose or hide variables and functions using H files?
Variable definition into .c file.
Variable declaration into .h file.
For creating the declaration basically copy the definition, add the extern
keyword and remove any initialization. Keep the qualifiers (const, volatile)
and any __attribute__
Exception 1: static
variables shall not get exposed, and for those nothing goes into the .h file.
Exception 2: variables with auto storage (defined inside a function) should not get exposed, and for those nothing goes into the .h file.
Note: Instead of exposing variables with extern
, consider to keep them private and instead create access functions (e.g. variable_get()
Function definition into .c file.
Function declaration into .h file.
For creating the declaration basically copy the definition, remove the function body and add a semicolon.
Exception 1: static
functions shall not get exposed, and for those nothing goes into the .h file.
Exception 2: For a static inline
function, which is used in only one .c file everything goes into that .c file and nothing into the .h file.
Exception 3: For a static inline
function, which is used in several .c files or .h files everything goes into an .h file of your choice and nothing into a .c file.
Exception 4: functions defined inside another function should not get exposed, and for those nothing goes into the .h file. typedef
, which is used in only one .c file, goes into that .c file and nothing goes into the .h file.typedef
, which is used in several .c files or .h files, goes into a .h file of your choice and nothing goes into a .c file.
Exception 1: typedef
defined inside another function should not get exposed, and for that nothing goes into the .h file.
naeem1234Where to declare and define variables or structs in C or H files?
A struct variable is a variable.
A struct typedef
is a typedef
For both see the previous answer.
naeem1234Should there be only 1 header file that contains all exposed variables and functions and include that in all C files or should there be as many H files as many C files in a project and include only the required H files in a C file?
Of course this is a style question. However, if your project gets really large, this 1 header file will get really huge and a real mess. Therefore, usually each .c file should have its own .h file. This gives your program some modularization. For each pair of .c and .h file, the .h file describes the interface to a logical module, and the .c file actually implements it.
However, it is OK to have additional .h files, which don't have a .c file, typically for typedef
, and static inline
functions. Furthermore, sometimes you might also have a logical module which has two or more interfaces. And one other .c file might use interface A and a second other .c file might use interface B. Therefore, it makes sense to declare each interface in an own .h file, although they get implemented by the same .c file. For example: module.c, module_interface_A.h, module_interface_B.h.
In each .c and each .h file you usually only include the required .h files. However, if you have a very general .h file, which you use in the majority of .c files, it is also common to include that one in all .c files, and don't care if it is actually required.
naeem1234Is it ok to include H files in another H file?
Yes. Examples include:
- In one .h file you are using a type from a typedef
in a second .h file.
- In one .h file you have a static inline
function, which uses a function, or an extern
variable from a second .h file.
- In one .h file you have whatever, which uses a #define
from a second .h file.
However, as soon as you have an .h file which include other .h files you should use include guards, at least in all those included .h files. Those include guards prevent double inclusion. Better, you use them in all .h files by default.
However, avoid include circles. Those are evil and make your head hurt. ;-)
And if you follow my advice about include circles, you don't need to read the rest of this post:
If you have a circle you should first think again about your code structure and if your logical splitting into files really makes sense.
If you have a circle because of types, you could create an additional .h file for the types.
If you really think there is nothing wrong with your modularization and this circle can't be avoided, then this is a case where you should create additional .h files:
Remove from A.h everything which needs any stuff from B.h and place it into an own A2.h.
Remove from B.h everything which needs any stuff from A.h and place it into an own B2.h.
After this hopefully,
A2.h only needs to include B.h, and not B2.h, or
B2.h only needs to include A.h, and not A2.h.
If one of those two conditions is true, you are happy. Otherwise, you are screwed, and probably did not really think about your code structure, and ... What the hell are you actually trying to do?!?!?
post edited by moser - 2020/07/08 11:06:00