C and C++ use a special component in their compilers called a preprocessor. Itâs basically a fancy copy-paste machine.
Firstly a breakdown of what all the different preprocessor words mean (you can skip this if youâre sure you know how they work).
#define
defines a word to mean something else.
E.g. #define FIVE 5
would result in all instances of FIVE
being replaced with 5
.
#if
tests if a condition is true.
#else
provides an alternative case for an #if
, in case it is not true.
#endif
ends an #if
e.g.
#if VERSION > 5
useNewFeature();
#else
useOldFeature();
#endif
#ifdef
tests if a word is defined and #ifndef
does the opposite - it tests if a word has not been defined.
e.g.
#define FIVE
#ifdef FIVE
// This is used
#else
// This isn't
#endif
So now thatâs out of the way, letâs examine this.
#ifndef BITMAPS_H
#define BITMAPS_H
// lots of bitmaps
#endif
The correct name for this sequence is a âinclude guardâ.
This says âif BITMAPS_H isnât defined, define it, then look at this C++ codeâ which implicitly means âif BITMAPS_H is defined, ignore all this codeâ.
What this results in is a block of code that can only be examined once. This is done for a good reason - trying to read certain bits of code twice will upset the compiler because it will think you are trying to redefine something you have already stated.
The compiler doesnât realise itâs the same file and doesnât know to ignore it unless you use that special define sequence.
If your wondering why the compiler might try to read it twice, thatâs because of how #include
works.
#include
is basically a copy-paste. #include "file.h"
says 'copy the contents of file.h
and paste it all here. This means that if file.h
gets #include
d more than once, youâll have duplicate sets of code, which is why you need the include guards - to make sure the compiler ignores the duplicates.
As youâve pointed out, there are two kinds of includes, and they both have different behaviour. The difference is where the preprocessor looks for the file.
If you use the quote syntax #include "bitmaps.h"
then the preprocessor will look for the file locally. E.g. if you had a file âProject/Main.hâ and it had a line #include "Other.h"
, the preprocessor would look for âProject/Other.hâ.
The angle bracket syntax on the other hand, looks for the file in a specially designated library folder and it typically used for external libraries.
What this means is that for files local to your project you want to use the quote-style #include "bitmaps.h"
and for external librarys you want to use angle-bracket-style, like when you #include <Arduboy2.h>
.
I hope that all makes sense.
Post Script:
There are a few details Iâve left out like #if defined(WORD)
and #pragma once
, but you donât need to know about those unless youâre really curious.