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.

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:

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?
- If we need to use the functionality that functions 1 and 2 implement somewhere else, then Yes
- If macro 2 is intended only for use in the files Unit1.c and Unit2.c, then it has no place in the interface file.
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:

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,
- the header file contains only those declarations of functions, types, macros that are part of the interface of this module.
- The C-file, in turn, must contain the implementation of all the functions declared in the h-file, as well as private types, macros and functions that are needed to implement the interface.
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):

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.

')
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.