Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Заголовочные файлы в C: типы, подключение и лучшие практики

Заголовочный файл — это файл с расширением .h, содержащий объявления функций, макросов, констант и типов, которые нужно разделять между несколькими файлами исходного кода. Существует два вида заголовочных файлов:

Чтобы использовать заголовочный файл, его подключают директивой препроцессора #include — например, #include <stdio.h>.

Подключение заголовочного файла эквивалентно копированию его содержимого в место директивы, но ручное копирование — плохая идея: это источник ошибок и усложняет поддержку, особенно в проектах с множеством .c-файлов.

Хорошая практика: хранить в заголовочных файлах константы, макросы, прототипы функций и глобальные переменные (с extern), а определения — в .c-файлах.

Синтаксис #include

Директива имеет две формы:

#include <file>

Используется для системных заголовочных файлов. Препроцессор ищет файл в стандартных системных каталогах. Список каталогов можно расширить ключом компилятора -I.

#include "file"

Используется для пользовательских заголовочных файлов. Поиск начинается в каталоге, где лежит текущий исходный файл. Тоже можно расширить через -I.

Как работает #include

Директива заставляет препроцессор обработать указанный файл как входной поток перед продолжением текущего файла. На выходе получается: уже обработанный текст, затем текст из подключаемого файла, затем остаток текущего файла после директивы.

Пример. Файл header.h:

char *test(void);

Файл program.c:

int x;
#include "header.h"
int main(void) {
    puts(test());
}

Компилятор видит то же, что если бы program.c содержал:

int x;
char *test(void);
int main(void) {
    puts(test());
}

Защита от повторного включения (Include Guards)

Если заголовочный файл подключить дважды, компилятор увидит его содержимое дважды — будет ошибка переопределения. Стандартная защита — обернуть всё содержимое в условный блок:

#ifndef HEADER_FILE
#define HEADER_FILE
/* всё содержимое заголовочного файла */
#endif

Эта конструкция называется include guard (или wrapper #ifndef). При повторном включении макрос HEADER_FILE уже определён, условие ложно, и препроцессор пропускает содержимое.

В современном C (C11 и выше) также можно использовать #pragma once — это короче и поддерживается всеми основными компиляторами.

Вычисляемые включения (Computed Includes)

Иногда нужно выбрать один из нескольких заголовочных файлов в зависимости от конфигурации (например, под разные ОС). Можно использовать цепочку условий:

#if SYSTEM_1
# include "system_1.h"
#elif SYSTEM_2
# include "system_2.h"
#elif SYSTEM_3
...
#endif

Но при росте вариантов это становится громоздко. Препроцессор позволяет использовать макрос в качестве имени файла — это называется вычисляемое включение:

#define SYSTEM_H "system_1.h"
...
#include SYSTEM_H

Макрос SYSTEM_H раскроется в строку "system_1.h", и препроцессор подключит именно этот файл. Значение макроса можно задать из Makefile через -DSYSTEM_H="system_2.h".

Язык C

  1. Работа с файлами в C: мастерство ввода-вывода с fopen, fprintf, fread и fseek
  2. Работа с файлами в Python: открытие, чтение, запись и управление
  3. Мастерство файловых операций в Java с java.io: создание, чтение, запись и удаление
  4. Понимание STL-файлов: основа 3D-печати
  5. Работа с файлами в Verilog: открытие, чтение, запись и закрытие
  6. Освоение ввода-вывода файлов в C: создание, открытие и управление файлами
  7. Ввод-вывод в файлы в C++: чтение и запись с fstream
  8. Работа с файлами в C#: FileStream, StreamReader, StreamWriter и File API
  9. Ввод-вывод файлов в Python: полное руководство по операциям I/O
  10. Треугольная наждачная напильник: конструкция, применение и уход