In C/C++, the preprocessor performs operations before compilation. What this means is that we can give directives to the preprocessor through the pound sign #. Macros are identifiers with values.

Preprocessor directives include:

  • #include: for calling header files, like stdlib.h. We (usually) never include any file with executable code.
  • #define: for setting macros, often for constants.
  • #ifndef: checks if something is defined. Used in conjunction with #define and #endif.
  • #undef: for undefining previously defined macros.
  • #error: to tell the compiler to get the fuck out if it gets there. Typically used inside a conditional to prevent compilation if some pre-requisite isn’t met.

Under the hood

Pre-processing textually replaces #include "file_name" with the contents of the file. Technically speaking, we can #include a .cpp file instead of a .h file — but this is bad practice. Usually the .cpp file contains the implementations of the content, and this can easily re-define functions or classes. This can happen too with .h files, so we use the #ifndef preprocessor.

#ifndef A_H
#define A_H
struct A {
	// definition
}
#endif