📜 ⬆️ ⬇️

What should be in the c-file, and what should be in the h-file?

This kind of question I was recently asked by a colleague who starts programming in C language. And I thought that this is a good reason to share my understanding of this issue. Because even experienced programmers do not always have similar points of view on this matter.

In part, this is a matter of taste, so who cares how I do it, welcome under the cat.

Despite the fact that “the whole truth” about h-files is contained in the corresponding section of the gcc preprocessor description, I will allow myself some explanations and illustrations.

So, if literally, the header file (h-file) is a file containing C declarations and macro definitions, intended for use in several source files (c-files). We illustrate this.
image
It is easy to see that functions 1 and 2, as well as macro 2, are mentioned in both files. And since the inclusion of header files produces the same results as copying the contents into each C-file, we can do the following:
image
Thus, we simply selected the common part of the two files and placed it in the header file.
But is the header file an interface in this case?

Moreover, do we really need to have two C files to implement the interface defined in the header file? Or just one?
The answer to this question depends on the details of the implementation of the interface functions and on their place of implementation. For example, if you make the diagrams more detailed, you can imagine a variant when the interface functions are implemented in different files:
image
Such an embodiment leads to high code connectivity, low testability and the difficulty of reusing such modules.
In order not to have such difficulties, I always consider the C-file and the header file as one module. Wherein,

Thus, if I had the chance to implement the code to which the diagram above corresponds, I would try to achieve the following (the endings _c and _h in the file names were added because it was impossible to use a dot in the tool that I used to create diagrams):
image
The diagram shows that in fact we are dealing with two independent modules, each of which has its own interface in the form of a header file. This makes it possible to use only the interface that is really needed in this particular case. Moreover, these modules can be tested independently of each other.
The reader probably noticed that macro 2 from the header file was again returned as a copy to both C-files. Of course, it is not very convenient to maintain. But to make this macro part of the interface is not correct.
In such cases, I prefer to make a separate header file containing the types and macros needed by several C-files.
image
')
I hope I managed to identify those entities that need to be placed in the header files. And also show the difference between interfaces and files containing declarations and macros needed by several C-files.

Thank you for your attention to the material.

Source: https://habr.com/ru/post/280764/


All Articles