Любой заголовочный файл C/C++ должен иметь следующую структуру:
#ifndef ИМЯ_ЗАГОЛОВОЧНОГО_ФАЙЛА
#define ИМЯ_ЗАГОЛОВОЧНОГО_ФАЙЛА
/* здесь помещается остальной текст заголовочного файла */
#endif /* ИМЯ_ЗАГОЛОВОЧНОГО_ФАЙЛА: */
Например, заголовочный файл myFunctions.h, в котором размещены объявления функций f и g, будет выглядеть так:
#ifndef MY_FUNCTIONS_H
#define MY_FUNCTIONS_H
void f(int n);
double g(double a, double b);
#endif /* MY_FUNCTIONS_H: */
Директивы ifndef-define-endif, которые обрамляют любой грамотно оформленный заголовочный файл, являются трюком препроцессора: они обеспечивают то, что любой заголовочный файл будет включён в любой исходный файл не более одного раза.
Каждому заголовочному файлу «вручную» ставится в соответствие некоторый «символ», обычно связанный с именем этого файла, чтобы обеспечить уникальность. В первой строке проверяется, был ли уже определён этот символ ранее, если да, то весь остальной текст игнорируется. Если нет, то этот символ определяется, а затем вставляется и весь остальной текст заголовочного файла. Последняя строка (endif) просто означает закрытие такого «условного оператора».
На самом деле, если написать подряд две одинаковые директивы include для одного заголовочного файла, содержащего только объявления функций, то ничего страшного не произойдёт, даже если он не содержит стражей включения. Однако для более сложных элементов заголовочных файлов, таких как объявление enum или struct, попадание нескольких их экземпляров в один исходный файл может привести к ошибкам компиляции. Поскольку заголовочные файлы имеют тенденцию быстро изменяться и расти, считается необходимым всегда использовать стражи включения.