Реферат: Препроцессор языка C.
библиотеками.
Подключаемые файлы пользователя содержат определения для интерфейсов
между исходными файлами программы.
Включение подключаемого файла в программу дает такой же результат, как
при копировании этого файла в каждый исходный файл этой программы. Подобное
копирование занимает много времени и побуждает возникновение ошибок. При
использовании подключаемых файлов все объявления и определения переменных и
функций находятся в одном файле и при необходимости могут быть изменены.
Обычно подключаемые файлы заканчиваются на '.h' и следует избегать
использования других стандартов.
3.2. Директива '#include'.
Как файлы пользователя, так и системные файлы включаются в программу с
использованием директивы препроцессора '#include'. Она имеет три модификации:
'#include <FILE>'
Эта модификация используется для подключения системных файлов. При ее
выполнении производится поиск файла с именем FILE в списке указанных заранее
каталогов, а затем в стандартном списке системных каталогов. С помощью
опции '-I' указываются каталоги для поиска подключаемых файлов. Опция
'-nostdinc' запрещает поиск в стандартных системных каталогах и производит
поиск только в указанных каталогах.
Синтаксис такой модификации директивы '#include' довольно специфичен,
потому как комментарии внутри '<...>' не распознаются. Поэтому в строке
'#include <x/*y>' последовательность символов '/*' не начинает комментарий,
а указанная директива включает в программу файл с именем 'x/*y'.
Аргумент FILE не может содержать символа '>', хотя он может содержать
символ '<'.
'#include "FILE"'
Эта модификация применяется для подключаемых файлов для программ
пользователя. Сначала файл FILE просматривается в текущем каталоге, а затем
в каталогах для системных подключаемых файлов. Текущим каталогом является
каталог текущего обрабатываемого файла. Он просматривается в первую очередь,
так как предполагается, что в нем находятся файлы, имеющие отношение к
текущему обрабатываемому файлу. (Если указана опция '-I-', то текущий
каталог не просматривается.)
Аргумент FILE не может содержать символов '"'. Символы backslash
интерпретируются как отдельные символы, а не начало escape
последовательности. Таким образом, директива '#include "x\n\\y"' указывает
имя файла, содержащего три символа backslash.
'#include ANYTHING ELSE'
Эта модификация называется "вычисляемой директивой #include". Любая
директива '#include', не соответствующая ни одной из модификаций,
рассмотреных выше, является вычисляемой директивой. Строка ANYTHING ELSE
проверяется на наличие соответствующего макроса, значение которого затем
заменяет его название. Полученная в результате строка должна уже
в точности соответствовать одной из рассмотренных выше модификаций (то есть
имя подключаемого файла должно быть заключено в кавычки или угловые скобки).
Эта возможность позволяет определять макросы, что дает возможность
изменять имена подключаемых файлов. Эта возможность, например, используется
при переносе программ с одной операционной системы на другие, где требуются
разные подключаемые файлы.
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', которая используется для подключения следующего файла с
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10