Чтение онлайн

ЖАНРЫ

Язык Си - руководство для начинающих

Д. МАРТИН

Шрифт:

В-третьих, мы определили YES как 1, тогда как в файле bool.h мы определили TRUE как 1. Но здесь нет конфликта, и мы можем использовать слова YES и TRUE в одной и той же программе. Каждое из них будет заменяться на 1. Может возникнуть конфликт, если мы добавим в файл строку

#define TRUE 2

Второе определение вытеснило бы первое, и некоторые препроцессоры предупреждали бы вас, что TRUE переопределено.

Директива #include не ограничивается заголовочными файлами. Если вы записали нужную функцию

в файл sort.с, то можно использовать

#include "sort.с"

чтобы скомпилировать его совместно с вашей текущей программой.

Директивы #include и #define являются наиболее активно используемыми средствами препроцессора языка Си. Рассмотрим более сжато другие его директивы.

ДРУГИЕ ДИРЕКТИВЫ: #undef, #if, #ifdef, #ifndef, #else И #endif

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

Директива #undef отменяет самое последнее определение поименованного макроопределения.

#define BIG 3

#define HUGE 5

#undef BIG /* BIG теперь не определен */

#define HUGE 10 /* HUGE переопределен как 10 */

#undef HUGE /* HUGE снова равен 5*/

#undef HUGE /* HUGE теперь не определен */

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

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

Другие упомянутые нами директивы позволяют выполнять условную компиляцию. Вот пример:

#ifdef MAVIS

#include " horse.h" /* выполнится, если MAVIS определен */

#define STABLES 5

#else

#include "cow.h" /*выполнится, если MAVIS не определен */

#define STABLES 15

#endif

Директива #ifdef сообщает, что если последующий идентификатор (MAVIS) определяется препроцессором, то выполняются все последующие директивы вплоть до первого появления #else или #endif. Когда в программе есть #else, то программа от #else до #endif будет выполняться, если идентификатор не определен.

Такая структура очень напоминает конструкцию if-else языка Си. Основная разница заключается

в том, что препроцессор не распознает фигурные скобки {}, отмечающие блок, потому что он использует директивы #else (если есть) и #endif (которая должна быть) для пометки блоков директив.

Эти условные конструкции могут быть вложенными.

Директивы #ifdef и #if можно использовать с #else и #endif таким же образом. Директива #ifndef опрашивает, является ли последующий идентификатор неопределенным; эта директива противоположна #ifdef. Директива #if больше похожа на обычный оператор if языка Си. За ней следует константное выражение, которое считается истинным, если оно не равно нулю:

#if SYS == "IBM"

#include "ibm.h"

#endif

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

Эти краткие примеры иллюстрируют удивительную способность языка Си изощренно и строго управлять программами.

ЧТО ВЫ ДОЛЖНЫ БЫЛИ УЗНАТЬ В ЭТОЙ ГЛАВЕ

Как определять символьные константы директивой #define: #define FINGERS 10

Как включать другие файлы: #include "albanian.h"

Как определить макрофункцию: #define NEG(X) (-(X))

Когда использовать символические константы: часто.

Когда использовать макрофункции: иногда.

Опасность применения макрофункций: побочные эффекты.

ВОПРОСЫ И ОТВЕТЫ 

Вопросы

1. Ниже приведены группы операторов, содержащих по одному и более макроопре делений, за которыми следуют строки исходных кодов, использующих эти макро определения. Какой результат получается в каждом случае? Правилен ли он?

a. #define FPM 5280 /* футов в миле */

dist = FPM * miles;

б. #define FEET 4

#define POD FEET + FEET

plort = FEET * POD;

в. #define SIX = 6;

nex = SIX;

г. #define NEW(X) X + 5

у = NEW(y);

berg = NEW(berg) * lob;

est = NEW(berg) / NEW(y);

nilp = lob * NEW(-berg);

2. Подправьте определение в вопросе 1.г, чтобы сделать его более надежным.

3. Определите макрофункцию, которая возвращает минимальное из двух значений.

4. Задайте макроопределение, в котором есть функция whitesp(с) считающая в программе пустые символы.

5. Определите макрофункцию, которая печатает представления значения двух целых выражений.

Ответы

1.

а. dist = 5280 * miles; правильно.

б. plot = 4 * 4 + 4; правильно, но если пользователь на самом деле хотел иметь 4 * (4 + 4), то следовало применять директиву #define POD (FEET + FEET).

Поделиться с друзьями: