Опубликован: 26.06.2003 | Уровень: для всех | Доступ: платный
Лекция 14:

Компоновка программ, препроцессор

< Лекция 13 || Лекция 14: 123 || Лекция 15 >

Препроцессор

В языке Си++ имеется несколько директив, которые начинаются со знака #: #include, #define, #undef, #ifdef, #else, #if, #pragma. Все они обрабатываются так называемым препроцессором.

Иногда препроцессор называют макропроцессором, поскольку в нем определяются макросы. Директивы препроцессора начинаются со знака #, который должен быть первым символом в строке после пробелов.

Определение макросов

Форма директивы #define

#define имя определение

определяет макроимя. Везде, где в исходном файле встречается это имя, оно будет заменено его определением. Например, текст:

#define NAME "database"
Connect(NAME);

после препроцессора будет заменен на

Connect("database");

По умолчанию имя определяется как пустая строка, т.е. после директивы

#define XYZ

макроимя XYZ считается определенным со значением – пустой строкой.

Другая форма #define

#define имя ( список_имен ) определение

определяет макрос – текстовую подстановку с аргументами

#define max(X, Y) ((X > Y) ? X : Y)

Текст max(5, a) будет заменен на

((5 > a) ? 5 : a)

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

Директива #undef отменяет определение имени, после нее имя перестает быть определенным.

У препроцессора есть несколько макроимен, которые он определяет сам, их называют предопределенными именами. У разных компиляторов набор этих имен различен, но два определены всегда: __FILE__ и __LINE__. Значением макроимени __FILE__ является имя текущего исходного файла, заключенное в кавычки. Значением __LINE__ – номер текущей строки в файле. Эти макроимена часто используют для печати отладочной информации.

Условная компиляция

Исходный файл можно компилировать не целиком, а частями, используя директивы условной компиляции:

#if LEVEL > 3
текст1
#elif LEVEL > 1
текст2
#else
текст3
#endif

Предполагается, что LEVEL – это макроимя, поэтому выражение в директивах #if и #elif можно вычислить во время обработки исходного текста препроцессором.

Итак, если LEVEL больше 3, то компилироваться будет текст1, если LEVEL больше 1, то компилироваться будет текст2, в противном случае компилируется текст3. Блок условной компиляции должен завершаться директивой #endif.

В каком-то смысле директива #if похожа на условный оператор if. Однако, в отличие от него, условие – это константа, которая вычисляется на стадии препроцессора, и куски текста, не удовлетворяющие условию, просто игнорируются.

Директив #elif может быть несколько (либо вообще ни одной), директива #else также может быть опущена.

Директива   #ifdef – модификация условия компиляции. Условие считается выполненным, если указанное после нее макроимя определено. Соответственно, для директивы #ifndef условие выполнено, если имя не определено.

Дополнительные директивы препроцессора

Директива   #pragma используется для выдачи дополнительных указаний компилятору. Например, не выдавать предупреждений при компиляции, или вставить дополнительную информацию для отладчика. Конкретные возможности директивы #pragma у разных компиляторов различные.

Директива #error выдает сообщение и завершает компиляцию. Например, конструкция

#ifndef unix
#error "Программу можно компилировать
                           только для Unix!"
#endif

выдаст сообщение и не даст откомпилировать исходный файл, если макроимя unix не определено.

Директива #line изменяет номер строки и имя файла, которые хранятся в предопределенных макроименах __LINE__ и __FILE__.

Кроме директив, у препроцессора есть одна операция ##, которая соединяет строки, например A ## B.

< Лекция 13 || Лекция 14: 123 || Лекция 15 >
Андрей Одегов
Андрей Одегов
Язык программирования C++
Елена Шумова
Елена Шумова

Здравствуйте! Я у Вас прошла курс Язык программировая Си++.

Заказала сертификат. Хочу изменить способ оплаты. Как это сделать?

Евгений Медведев
Евгений Медведев
Россия, Кемерово, КузГТУ