Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Подбельский Фомин_Программирование на языке СИ_...doc
Скачиваний:
234
Добавлен:
10.08.2019
Размер:
53.81 Mб
Скачать

Глава 3. Препроцессорные средства

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

Несколько нетрадиционно для пособий по языку Си начнем дальнейшее изложение материала о возможностях препроцессора. Это позволит в следующих главах продемонстрировать эффективность препроцессорных средств и их применимость при решении разнородных задач. Откладывать, как часто принято, изучение препроцессора на конец курса по языку Си, по нашему мнению, не совсем удачно. Даже в начальных (вступительных) главах 1 и 2 пришлось затронуть некоторые важные вопросы препроцессорной обработки. Введены константы, определяемые директивой #define, проиллюстрированы некоторые правила включения в программу текстов заголовочных файлов для связи со стандартной библиотекой компилятора. Этих сведений вполне достаточно, чтобы программировать на языке Си, вводить с помощью #define собственные обозначения констант и не испытывать затруднений в использовании стандартных библиотек.

К сожалению, именно на таком уровне использования препроцессора остаются многие программисты, не обратившие внимания на другие возможности препроцессорной обработки текста программы. А возможности препроцессора весьма интересные, особенно в областях макрообработки и условной компиляции. Введя в этой главе препроцессорные средства, мы сможем в следующих главах показать способы и возможности их применения при решении задач разных классов.

Прежде чем перейти к изложению материала, отметим, что препроцессор обрабатывает почти любые тексты, а не только тексты программ на языке Си. Обработка программ - это основная задача препроцессора, однако он может преобразовывать произвольные тексты, и этой возможностью программисту не следует пренебрегать в своей работе.

Итак, на входе препроцессора - текст с препроцессорными директивами, на выходе препроцессора - текст без препроцессорных директив (см. рис. 1.1).

3.1. Стадии и команды препроцессорной обработки

В интегрированную среду подготовки программ на Си или в компилятор языка как обязательный компонент входит препроцессор. Назначение препроцессора - обработка исходного текста программы до ее компиляции (см. рис. 2.1).

Стадии препроцессорной обработки.

Стадии препроцессорной обработки. Препроцессорная обработка включает несколько стадий, выполняемых последовательно. Конкретная реализация может объединять несколько стадий, но результат должен быть таким, как если бы они выполнялись в следующем порядке:

• все системно-зависимые обозначения (например, системнозависимый индикатор конца строки) перекодируются в стандартные коды;

• каждая пара из символов '\' и "конец строки" вместе с пробелами между ними убираются, и тем самым следующая строка исходного текста присоединяется к строке, в которой находилась эта пара символов;

• в тексте (точнее, в тексте каждой отдельной строки) распознаются директивы и лексемы препроцессора, а каждый комментарий заменяется одним символом пустого промежутка;

• выполняются директивы препроцессора и производятся макроподстановки;

• эскейп-последовательности в символьных константах и символьных строках, например '\n' или '\xF2', заменяются на их эквиваленты (на соответствующие числовые коды);

• смежные символьные строки (строковые константы) конкатенируются, т.е. соединяются в одну строку;

• каждая препроцессорная лексема преобразуется в лексему языка Си.

Поясним, что понимается под препроцессорными лексемами или лексемами препроцессора (preprocessing token). К ним относятся символьные константы, имена включаемых файлов, идентификаторы, знаки операций, препроцессорные числа, знак препинания, строковые константы (строки) и любые символы, отличные от пробела. Можно сказать, что к лексемам препроцессора относятся лексемы языка Си, имена файлов и символы, не определенные иным способом.

Знакомство с перечисленными стадиями препроцессорной обработки объясняет, как реализуются некоторые правила синтаксиса языка. Например, становится понятным смысл утверждений: "каждая символьная строка может быть перенесена в файле на следующую строку, если использовать символ '\'", или "две символьные строки, записанные рядом, воспринимаются как одна строка". Отметим, что после "склеивания" строк в соответствии с приведенными правилами каждая полученная строка обрабатывается препроцессором отдельно.

Рассмотрим подробно стадию обработки директив препроцессора. При ее выполнении возможны следующие действия:

• замена идентификаторов (обозначений) заранее подготовленными последовательностями символов;

• включение в программу текстов из указанных файлов;

• исключение из программы отдельных частей ее текста (условная компиляция);

• макроподстановка, т.е. замена обозначения параметризованным текстом, формируемым препроцессором с учетом конкретных параметров (аргументов).