3.3. Как работает директива '#include'
Директива '#include' указывает С препроцессору обработать указанный
файл перед обработкой оставшейся части текущего файла. Информация, выдаваемая
препроцессором, содержит уже полученные данные, за которыми следуют данные,
получаемые при обработке подключаемого файла, а за которыми, в свою очередь,
следуют данные, получаемые при обработке текста, следующего после директивы
'#include'. Например, дан следующий подключаемый файл 'header.h':
char *test ();
и основная программа с именем 'program.c', использующая этот файл.
int x;
#include "header.h"
main ()
{
printf (test ());
}
Данные, полученные при обработке программы 'program.c' будут выглядеть
следующим образом:
int x;
char *test ();
main ()
{
printf (test ());
}
Для подключаемых файлов нет ограничений на объявления и
макроопределения. Любой фрагмент С программы может быть включен в другой
файл. Подключаемый файл может даже содержать начало выражения,
заканчивающееся в исходном файле или окончание выражения, начало которого
находится в исходном файле. Хотя комметарии и строковые константы не могут
начинаться подключаемом файле и продолжаться в исходном файле. Не завершенный
комментарий, стороковая или символьная константа в подключаемом файле
приводят к возникновению ошибки в конце файла.
Подключаемый файл может содержать начало или окончание сиснтаксической
конструкции, такой как определение функции.
Срока, следующая за директивой '#include' всегда является пустой и
добавляется С препроцессором даже если подключаемый файл не содержит
завершающий символ перевода строки.
3.4. Однократно подключаемые файлы
Часто случается, что подключаемый файл включает в себя другой файл. Это
может привести к тому, что отдельный файл будет подключаться неоднократно,
что может привести к возникновению ошибок, если файл определяет типы
структур или определения типов. Поэтому следует избегать многократного
подключения файлов.
Обычно это достигается путем заключения в условие всего содержимого
этого файла, как показано ниже:
#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN
Сам файл
#endif /* FILE_FOO_SEEN */
Макрос 'FILE_FOO_SEEN' указывает на то, что файл уже однажды вкючался.
В подключаемых файлах пользователя макрос не должен начинаться с символа
'_'. В системных подключаемых файлах его имя не должно начинаться с символа
'__' во избежание возникновения конфликтов с программами пользователя. Каким
бы ни был файл, имя макроса должно содержать имя файла и некоторый
дополнительный текст во избежание вознкновения конфликтов с другими
подключаемыми файлами.
Препроцессор GNU C построен таким образом, что обработке подключаемого
файла он проверяет наличие определенных конструкций и наиболее рационально
их обрабатывает. Препроцессор специально отмечает полное вложение файла в
условие '#ifndef'. Если в подключаемом файле содержится директива '#include',
указывающая на обрабатываемый файл, или макрос в директиве '#ifndef' уже
определен, то обрабатываемый файл полностью игнорируется.
Существует также специальная директива, указывающая препроцессору, что
файл должен быть включен не более одного раза. Эта директива называется
'#pragma once'. Она использовалась в дополнение к директиве '#ifndef' и
в настоящее время она устарела и не должна прменяться.
В объектно ориентированном языке С существует модификация директивы
'#include', называемая '#import', которая используется для вкючения файла
не более одного раза. При использовании директивы '#import' вместо
'#include' не требуется наличия условных оборотов для предотвращения
многократной обработки файла.
3.5. Подключаемые файлы и наследование
"Наследование" это то, что происходит, когда какой либо объект или
файл образует некоторую часть своего содержимого путем виртуального
копирования из другого объекта или файла. В случае подключаемых С файлов
наследование означает, что один файл включает другой файл, а затем заменяет
или добавляет что-либо.
Если наследуемый подключаемый файл и основной подключаемый файл имеют
различные имена, то такое наследование называется прямым. При этом
используется конструкция '#include "BASE"' в наследуемом файле.
Иногда необходимо чтобы у наследуемого и основного подключаемого файла
были одинаковые имена.
Например, предположим, что прикладная программа использует системный
подключаемый файл 'sys/signal.h', но версия файла '/usr/include/sys/signal.h'
на данной системе выполняет того, что требуется в прикладной программе.
Будет удобнее определить локальную версию, возможно с именем
'/usr/local/include/sys/signal.h' для замены или добавления к версии,
поставляемой с системой.
Это можно выполнить с применением опции '-I.' при компиляции, а также
созданием файла 'sys/signal.h' который выполняет требуемые программе функции.
Но сделать так, чтобы этот файл включал стандартный файл 'sys/signal.h' не
так просто. При включении строки '#include <sys/signal.h>' в этот файл
произойдет подключение новой версии файла, а не стандартной системной версии.
Это приведет к рекурсии и ошибке при компиляции.
При использовании директивы `#include </usr/include/sys/signal.h>'
нужный файл будет найден, но этот способ является не эфективным, так как
содержит полный путь к системному файлу. Это может отразиться на содержании
системы, так как это означает, что любые изменения местоположения системных
файлов потребуют дополнительных изменений где-либо еще.
Более эффективным решением этой проблемы является применение директивы
'#include_next', которая используется для подключения следующего файла с
таким же именем. Эта директива функционирует также как и директива '#include'
за исключением поиска требуемого файла. Она начинает поиск списка каталогов
подключаемых файлов после каталога, где был найден текущий файл.
Предположим была указана опция '-I /usr/local/include', а список
каталогов для поиска включает '/usr/include'. Также предположим, что оба
каталога содержат файл с именем 'sys/signal.h'. Директива
'#include <sys/signal.h>' найдет нужный файл под каталогом
'/usr/local/include'. Если этот файл содержит строку
'#include_next <sys/signal.h>', то поиск будет возобновлен после предыдущего
каталога и будет найден файл в каталоге '/usr/include'.
... 1-12. Напишите программу, печатающую гистограмму длин слов из файла ввода. Самое легкое - начертить гистограмму горизон- тально; вертикальная ориентация требует больших усилий. 1.7. Функции. В языке “C” функции эквивалентны подпрограммам или функ- циям в фортране или процедурам в PL/1, паскале и т.д. Функ- ции дают удобный способ заключения некоторой части вычисле- ний в черный ...
... , сложны для понимания и абсолютно непрозрачны, а возможности существенно уступают Форту и Лиспу. В общем, муть и мрак. Вавилонское столпотворение Всякий раз, когда появляется очередной новый язык, о котором говорят, как об «окончательном и безальтернативном», предрекая скорую смерть всех остальных, мне становится смешно. Сам по себе язык в отрыве от среды программирования —малоинтересен, да и все ...
... программе. В данном разделе они перечислены в алфавитном порядке и приводятся с объяснениями. Эти ошибки могут являться следствием случайного затирание памяти программой. Abnormal program termination Аварийное завершение программы Данное сообщение может появляться, если для выполнения программы не может быть выделено достаточного количества памяти. Более подробно оно рассматривается в конце ...
... доступа с записью равной байту. Такие файлы называются двоичными. Файлы прямого доступа незаменимы при написании программ, которые должны работать с большими объемами информации, хранящимися на внешних устройствах. В основе обработке СУБД лежат файлы прямого доступа. Кратко изложим основные положения работы с файлами прямого доступа. 1). Каждая запись в файле прямого доступа имеет свой номер ...
0 комментариев