The split between compiler and preprocessor is important here. Notice how #include starts with an #, that is a preprocessor directive.
If you are a messy programmer, you can even use #include "library.c" at the top of the header to merge in the entire C file, at that point, before going to the compiler.
There are already too many messy programmers around, so please don't do that. (except when actually useful, as with compile-time script generated lookup tables)
Instead, create functional modules that can be tested as a module, which have one header and 1 or more C files, instead of one C file with 10k lines.
I know you're just waiting for an example, so here is an header as I often use them, from memory:
#ifndef HEADER_H
#define HEADER_H
// https://en.wikipedia.org/wiki/Include_guard
#include <inttypes.h>
// Dependencies
#include "otherModule.h"
// Typedefs and such...
// Publics
extern int hdr_publicParameter1;
// Api, prefixed with hdr, since there can't be a duplicate object name in the linker stage.
void hdr_moduleInit();
void hdr_transmit(const char *stuff);
uint8_t hdr_isReady();
void hdr_deinit();
// Defines
#define hdr_doInlineThingy(x) (x+6)
#endif //HEADER_H
C files look like this, using static to prevent being messy with globals.
#include <stdstuff.h>
#include "header.h"
// Constants
const int settingA = 6; /// Set A feature speed.
const int settingB = 9; /// Set B feature count.
// Private routines
static void hdr_processParam();
static void hdr_clearMem();
// Private variables (private to the module that is)
static int elapsedTime; /// Time elapsed during transmit.
static int eventCounter; /// Counter for events.
// publics
extern int hdr_publicParameter1; /// Doxygen brief.
// Private routines
/** @brief processes the parameters
* Processes of the parameters according y=ax+b
*/
void hdr_processParam(){
static int counter; // Persistent variable, but not public.
}
...
// Public routines
/** @brief processes the parameters
* Processes of the parameters according y=ax+b
*/
void hdr_moduleInit(){
}
...
Yes, I know they are not strictly structured. This I only see when there is teaming with more than two people.
This all navigates fine with an IDE that has right-click->GoTo features. Doxygen is also nice in generating live popups of the function brief when autocompleting and such.
When done, you need to add the C files to your makefile. And the include paths of the headers.