В ANSI С не требуется строгое соблюдение модели каталогов для файлов, т.к. не все вычислительные системы организованы одинаково. Вообще говоря, метод, применяемый для именования файлов, зависит от системы, но использование угловых скобок и двойных кавычек — нет.
Зачем включать файлы? Причина в том, что они содержат информацию, которая необходима компилятору. Например, файл stdio.h обычно содержит определения EOF, NULL, getchar() и putchar(). Два последних определены как функциональные макросы. Он также содержит прототипы функций ввода-вывода С.
Препроцессор и библиотека С 675
Суффикс.h традиционно применяется для заголовочных файлов — файлов с информацией, которая помещается в начале программы. Заголовочные файлы часто содержат операторы препроцессора. Некоторые из них, например, stdio.h, предоставляются системой, но вы можете создавать собственные заголовочные файлы.
Включение крупного заголовочного файла не обязательно приводит к значительному увеличению размера программы. Содержимое заголовочных файлов по большей части является информацией, которая используется компилятором для генерации окончательного кода, а не материалом, добавляемым к этому коду.
Пример заголовочного файла
Предположим, вы разработали структуру для хранения имени и фамилии лица, а также написали функции для работы с этой структурой. Всевозможные объявления вы могли бы собрать вместе внутри заголовочного файла. В листинге 16.6 приведен пример такого файла.
Листинг 16.6. Заголовочный файл names_st.li

Этот заголовочный файл содержит множество типичных для таких файлов элементов: директивы #define, объявления структур, операторы typedef и прототипы функций. Обратите внимание, что ни один из этих элементов не является исполняемым кодом; они представляют собой информацию, применяемую компилятором при создании исполняемого кода.
Показанный заголовочный файл довольно прямолинеен. Обычно вы должны использовать #ifndef и #define, чтобы защититься от многократных включений заголовочного файла. Мы возвратимся к этому приему позже.
Исполняемый код обычно размещается в файле исходного кода, а не в заголовочном файле. Например, в листинге 16.7 показаны определения функций, соответствующие прототипам функций из заголовочного файла. В нем включается заголовочный файл, поэтому компилятору будет знать о типе names st.
Листинг 16.7. Исходный файл name_st.c
// names_st.c -- определение функций для names_st #include
#include "namesst.h" // включение заголовочного файла
676 глава 16

В функции get names() применяется fgets() (через s_gets()), чтобы избежать переполнения целевых массивов. В листинге 16.8 приведен пример программы, в которой используются показанные ранее заголовочный файл и файл исходного кода.
Листинг 16.8. Программа useheader. с

Вот результаты пробного запуска:
Введите свое имя: Иван
Введите свою фамилию: Иванов
Добро пожаловать в программу, Иван Иванов!
Препроцессор и библиотека С 677
Обратите внимание на следующие аспекты программы.
• В обоих файлах исходного кода применяется структура names st, поэтому они оба должны включать заголовочный файл names st.h.
• Необходимо компилировать и компоновать файлы исходного кода names_st. с и useheader.с.
• Объявления и другие элементы подобного рода содержатся в заголовочном файле names_st.li; определения функций размещены в файле исходного кода
names_st.с.
Случаи применения заголовочных файлов
Просмотр содержимого стандартных заголовочных файлов поможет получить представление о том, какого рода информация в них находится. Ниже перечислено наиболее распространенное содержимое этих файлов.
• Символические константы. В типичном файле stdio.h, к примеру, определены константы EOF, NULL и BUFSIZ (размер стандартного буфера ввода-вывода).
• Функциональные макросы. Например, функция getchar() обычно определена как getc (stdin) , а getc() — в форме довольно сложного макроса. Заголовочный файл ctype.li, как правило, содержит определения макросов для функций ctype.
Читать дальше