Стражи включения
Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 2 из 61.
Когда заголовочный файл включается в проект несколько раз, компилятор видит одни и те же объявления повторно, что приводит к ошибкам. Это часто случается, когда несколько файлов включают один и тот же заголовочный файл или когда заголовочные файлы включают друг друга. Стражи включения (include guards) решают эту проблему.
Include guard использует три директивы препроцессора, чтобы гарантировать, что содержимое заголовочного файла будет обработано только один раз:
// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
#endif
Вот как это работает: #ifndef MATH_UTILS_H проверяет, не был ли символ MATH_UTILS_H определен ранее. Если он еще не определен, препроцессор продолжает работу и немедленно определяет его с помощью #define MATH_UTILS_H. Все, что находится между этой точкой и #endif, включается в компиляцию.
При втором включении этого заголовочного файла MATH_UTILS_H уже определен, поэтому весь блок пропускается. Имя стража обычно представляет собой имя файла в верхнем регистре, где точки и специальные символы заменены на подчеркивания.
Каждый создаваемый вами заголовочный файл должен иметь защиту от повторного включения (include guards). Это стандартная практика, которая предотвращает ошибки компиляции и делает ваш код безопасным для подключения из любого места вашего проекта.
Задание
ЛегкоДавайте защитим заголовочный файл от двойного включения, добавив include guards (защиту включения). Вы будете опираться на утилиту приветствия из предыдущего урока, но на этот раз убедитесь, что заголовочный файл можно безопасно включать несколько раз.
Вы создадите два файла:
greet.h: Ваш заголовочный файл, содержащий объявление функцииgreet. На этот раз оберните все содержимое защитой включения, используя символGREET_H.main.c: Ваш основной файл, который включает заголовочный файл, реализует функциюgreetи вызывает ее изmain().
Функция greet должна принимать параметр const char* для имени и выводить:
Hello, Alice!Ваш заголовочный файл должен иметь следующую структуру:
#ifndef GREET_H
#define GREET_H
// function declaration here
#endifВы получите один входной параметр: имя (строка).
Выведите приветственное сообщение точно в том формате, который показан выше, заменив Alice на предоставленное имя.
Шпаргалка
Include guards (стражи включения) предотвращают многократную обработку заголовочных файлов во время компиляции, что привело бы к ошибкам.
Страж включения использует три директивы препроцессора:
#ifndef HEADER_NAME_H
#define HEADER_NAME_H
// содержимое заголовка здесь
#endif
#ifndef проверяет, не был ли определен символ. Если он не определен, #define определяет его, и содержимое обрабатывается. При последующих включениях символ уже определен, поэтому весь блок пропускается.
Имя стража обычно представляет собой имя файла в верхнем регистре, где точки и специальные символы заменены на подчеркивания.
Каждый заголовочный файл должен иметь стражи включения в качестве стандартной практики.
Попробуйте сами
#include <stdio.h>
#include "greet.h"
// TODO: Реализуйте функцию greet, которая выводит "Hello, <name>!"
int main() {
char name[100];
scanf("%s", name);
// TODO: Вызовите функцию greet с name
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация круга