speller is a program with multiple source code files (speller.c
, dictionary.c
, and you may even have your own additional source code files). dictionary.h
is a header file and a header file is just an interface. So dictionary.h
is an interface for the functionality provided by dictionary.c
.
To be able to use this functionality in other source code files, you need to have the appropriate declarations and definitions before you use it. Having a header file for that purpose typically makes life easier as you don't have to copy/paste the declarations and the definitions across all the source code files that use the functionality of dictionary.c
, you don't have to worry about handling duplicated declarations, etc.
Without having a header file, it could be a pain if you later decided not to use some function/construct or maybe to add a helper function/construct as you'd have to go to all the files that use this functionality and modify them one by one (e.g., add/remove function declarations).
So thanks to header files, all you have to do is to include dictionary.h
, modify it as necessary, and there you have everything set up in all the other files that use it.
Also separating definitions from the interface in such a way is an illustration of an important computer science concept, namely information hiding (aka encapsulation).
Watch the short on libraries for more info!
Update: answering the question in the comment
when you use functions like load
, ... in speller.c
and include dictionary.h
atop of it, you're essentially telling the compiler "just treat these functions as if they are defined and I promise I'll define them later".
when you then compile the program, and per the Makefile
, you're compiling both speller.c
and dictionary.c
and linking the object (.o) files of them together.
at this point, the linker looks for the definitions of the functions that you promised to define and finds them in dictionary.o
so it provides a reference to them.