School me on pre-processor, pre-compiler, purpose?

So I've been looking at and using pre-processor commands but not fully understanding why, basically anything that starts with a #

#include

#if

etc...

What exactly is the purpose of preprocessor / precompiler commands and macros? It seems I can do the same thing using a function. So why use preprocessor / precompiler commands?

School me pls.

Thanks!

It seems I can do the same thing using a function.

Can you include a library using a function ?

Can you cause the compiler to produce different code depending on the processing environment using a function ?

Can you include or exclude debugging code in the program using a function ?

The key thing is that it is a preprocessor. It acts on the source code before the compiler gets to work.

One thing the pre-processor does is replacing macros

#define _PI 3.14
Serial.print(_PI);

The pre-processor will change the code to

Serial.print(3.14);

You could write a function called _PI that would return 3.14, but it would occupy some memory and slow your code down (just a little bit).

Another thing is a convenient way to enable specific parts of the code which can speed up the compile process. Functions will always be compiled; with a non-optimising compiler / linker, the function willl be in the executable, even if not used; with optimising compilers / linkers, the linker will now throw away the function if it is not used. the below yourFunction will not be compiled

// uncomment to compile myFunction
//#define COMPILE_MY_FUNCTION
#ifdef COMPILE_MY_FUNCTION
void myFunction()
{
  ...
  ...
}

#defines also provide a convenient way to prevent double includes which could result in compiler errors.

#ifndef ABC_H
#define ABC_H
  int x;
  ...
#endif

E.g. Arduino.h includes somefile.h which includes someotherfile.h which again includes Arduino.h. Without the so-called guard, you will have a problem.