Yes, there can be problems. This can be counteracted by remembering that the file name does not make a header file. Having headers, i.e. forward declaration does make a C file a header file. They seams to be an aversion to include *.c files, but in my opinion doing the same in a *.h file makes the problem only worse.

I think what is the right approach is to make sure, that a header file really only contains the "public" API. Common definitions or static/inline functions should be better put into a separate *.c file that is then included in multiple translation units, but since it is separate from the real API, it can be included in much less other files. Some also use the convention to name this files *.inc or *.imp .

As for name conflicts, C has the tooling for this, as compilation and symbol handling are separate steps. It might not be the cleanest approach, but you can always bundle some translation units into a convenience library and apply a linker script, or strip symbols with objcopy.

Symbols names before compilation can be influenced with the preprocessor by naming a macro with the same name, which essentially renames the symbol. For the mentioned conflict of preprocessor names (aka. macros), I see no other way short of modifying the code or undefining/redefining. Most people also use a build system which can trivially call out to sed, before invoking the compiler.