I recently realized that while it is illegal to ever define something more than once in a given translation unit, it is perfectly legal to declare things (functions, variables, structs) as many times as you like. I was under the impression that the purpose of include guards was to prevent duplicate declarations.
In fact, their purpose seems to be to prevent duplicate definitions. However, since function and variable definitions properly belong in .c files and not .h files and only .h files are #include'd, this would seem to imply that only structs and unions present a problem (because we typically define them in .h files, not just declare them). (Even the example on the wikipedia page on include guards uses struct definitions).
My question is: why is it so common to define structs in header files? Couldn't we just declare them in header files and then put their definitions in .c files and then include guards would be completely unnecessary since duplicate declarations are okay?
If I had to guess, it's because if we did this, the only thing that source files that include such header files would be able to so is create pointers to the structs since the definition of what fields they contain is in some other .c file. Is that accurate?