IMO they are the #1 reason C still has a lot of adoption, but not for good reasons: headers hinder interoperability. To interop with C you either need a C-compatible compiler (C++, Obj-C, and now D, Zig) or a human writing interop code by hand. Both things come with a hefty cost, and the first carries the danger of your language having to keep terrible features forever (the C part of C++).
Headers hinder the evolution of the language and the ecosystem.
Modules, on the other hand, enable interop easily, preventing lock-in.
It's the other way around - C is so easy to interop to that you don't even need to do anything. Modules, on the other hand, or such an effective lock-in that you can't reasonably automate the interop with it.
With a C header, all I need to do is run a single command that generates interfaces based on it for almost every language there is. Try that with any module-based system.
That's the approach I took; this brings the limitation that the only thing that can be publicly exported from a module are things that are compatible with C code.
It also makes modules useless - what use would a module be if the interface is fully specified in a header anyway? Just read the header.
TBH, I'm still in the design phase so I tend to change my idea of what's good and bad quite frequently.
But then all macros go to headers, even private ones. Also inline functions.
I don't understand what you mean by this; specifically, whats so special about macros? You can always define module-private macros in the .c file and not in the header like with any other symbol.
Yes, headers do mean that if modules A, B and C have shared private information then that information is not private (as it is shared via a header), but it doesn't mean that A cannot have private information that is visible only to A.
Headers have some really unbeatable advantages over module interfaces: the tooling is incomparable plus the header serves as the API documentation.
While modules are great, in practice you have interop problems and you still need a tool (if it is a binary file) to extract the interfacing API.
Modules are better from an elegance and clean-design PoV, but headers win on the practicality.