Читаем Внутреннее устройство Linux полностью

Исправление проблем, вызванных включаемыми файлами

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

badinclude.c:1:22: fatal error: notfound.h: No such file or directory

Это сообщение говорит о том, что компилятор не может найти заголовочный файл notfound.h, на который ссылается файл badinclude.c. Эта ошибка является прямым следствием такой директивы в первой строке файла badinclude.c:

#include

По умолчанию в Unix каталогом для включаемых файлов является /usr/include; компилятор всегда просматривает его, если вы явно не укажете ему не выполнять этого. Тем не менее можно настроить компилятор так, чтобы он просматривал другие каталоги (большинство каталогов с заголовочными файлами содержит слово include где-либо в своем имени).

примечание

Из главы 16 вы узнаете о том, как отыскать отсутствующие включаемые файлы.

Предположим, вы обнаружили файл notfound.h в каталоге /usr/junk/include. Можно сделать так, чтобы компилятор видел этот каталог с помощью параметра — I:

$ cc — c -I/usr/junk/include badinclude.c

Теперь компилятор не должен спотыкаться на строке кода в файле badinclude.c, которая ссылается на заголовочный файл.

Следует также опасаться включаемых файлов, использующих двойные кавычки (" ") вместо угловых скобок (< >), например так:

#include "myheader.h"

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

Что такое препроцессор C (cpp)?

Оказывается, компилятор C не выполняет работу по отыскиванию всех этих включаемых файлов. Эта задача приходится на долю препроцессора C — команды, которую компилятор применяет к исходному коду, прежде чем выполнить синтаксический анализ реальной программы. Препроцессор перезаписывает исходный код в такой форме, которую способен понять компилятор; это инструмент, делающий исходный код более легким для чтения (и снабжающий его обходными маневрами).

Команды препроцессора в исходном коде называются директивами, они начинаются с символа #. Существуют три основных типа директив.

Включаемые файлы. Директива #include дает препроцессору указание о том, чтобы он включил весь файл. Обратите внимание на то, что флаг компилятора — I является в действительности параметром, который вынуждает препроцессор искать включаемые файлы в указанном каталоге, как вы видели в предыдущем разделе.

 Макроопределения. Строка, подобная #define BLAH something, говорит препроцессору о том, чтобы он выполнил замену всех вхождений элемента BLAH на элемент something в исходном коде. По соглашению названия макроопределений даются прописными буквами, но не следует удивляться тому, что программисты иногда используют макроопределения, имена которых похожи на функции и переменные. Сплошь и рядом это причиняет массу неприятностей. Многие программисты превращают в спорт неправильное использование препроцессора.

примечание

Вместо того чтобы приводить макроопределения в исходном коде, можно также передавать параметры в компилятор: команда — DBLAH=something будет работать так же, как приведенная выше директива.

 Условные операторы. Можно пометить отдельные фрагменты кода с помощью слов #ifdef, #if и #endif. Директива #ifdef MACRO проверяет, определено ли макроопределение MACRO для препроцессора, а директива #if condition проверяет, является ли результат условия condition ненулевым. Для обеих директив в том случае, когда условие, следующее за директивой if, является ложным, препроцессор не передает компилятору текст программы, который расположен между директивами #if и #endif. Следует привыкнуть к этому, если вы собираетесь исследовать какой-либо код на языке C.

Приведу далее пример условной директивы. Когда препроцессор встречает такой код, он проверяет, есть ли макроопределение DEBUG, и если оно определено, передает компилятору строку, содержащую команду fprintf(). В противном случае препроцессор пропускает эту строку и продолжает обработку файла после директивы #endif:

#ifdef DEBUG

fprintf(stderr, "This is a debugging message.\n");

#endif

примечание

Препроцессор C ничего не знает о синтаксисе языка C, переменных, функциях и других элементах. Он понимает только свои собственные макроопределения и директивы.

В Unix препроцессор C называется cpp, но можно также запускать его с помощью команды gcc — E. Однако вам нечасто понадобится запускать препроцессор как таковой.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных