If I remember well the meaning of each term:
- preprocessing is the fact of interpreting/executing all lines which begin by # and if what follows is not recognized as having a valid syntax, it will be reported as an error;
- compilation is the fact of translating the source code to object code; if you don't respect the syntax of the language, an error will be reported;
- linking is the fact of taking one or multiple object files and creating one executable file out of them, thus verifying that everything which was declared and used is also defined.
Preprocessing error: `abcdefg' is not a valid keyword so preprocessing will fail:
#abcdefg
Compilation error: `fight!now' is not a valid identifier so compilation will fail:
int fight!now;
Linking error: `myfunc' is declared by never defined:
extern int myfunc();
int main() {
return myfunc();
}
You see, knowing where the tool chain detects the error helps knowing what kind of error it could be. But often the messages the tool chain emits is enough to understand where the error resides. Of course it requires being used to passing parameters as -Wall or even -Wextra to get more warnings about what could be wrong.