Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на C / C++ / Основы программирования на Си.doc
Скачиваний:
362
Добавлен:
02.05.2014
Размер:
1.3 Mб
Скачать

Символические константы: #define

Если в качестве первого символа в строке программы используется символ #, то эта строка является командной строкой препроцессора (макропроцессора). Командная строка препроцессора заканчивается символом перевода на новую строку. Если непосредственно перед концом строки поставить символ обратной косой черты "\", то командная строка будет продолжена на следующую строку программы.

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

Замена идентификаторов

#define идентификатор строка

Пример:

#define ABC 100

Заменяет каждое вхождение идентификатора ABC в тексте программы на 100:

#undef идентификатор

Пример:

#undef ABC

Отменяет предыдущее определение для идентификатора ABC.

Пример:

/* Простые примеры директивы препроцессора */

#define TWO 2 /* можно использовать комментарии*/

#define MSG "Текст 1.\

Продолжение текста 1"

/* обратная косая черта продолжает определение на следующую строку */

#define FOUR TWO*TWO

#define PX printf("X равен %d.\n", x)

#define FMT "X равен %d.\n"

main( )

{

int x = TWO;

PX;

x = FOUR;

printf(FMT,x);

printf("%s\n",MSG);

printf("TWO:MSG\n");

}

В результате выполнения нашего примера будем иметь:

X равен 2

X равен 4

Текст 1.

Продолжение текста 1

TWO: MSG

Разберем, что произошло. Оператор

int x = TWO;

превращается в

int x = 2;

Затем оператор

PX;

превращается в

printf("X равно %d.\n",x);

поскольку сделана полная замена. Теперь мы видим, что макроопределение может представлять любую строку, даже целое выражение на языке Си. Заметим, что это константная строка. PX напечатает только переменную, названную x.

В следующей строке выполняется следующее:

x = FOUR;

превращается

x = TWO*TWO;

превращается в

x = 2*2;

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

printf(FMT,x);

превращается в

printf("X равно %d.\n",x)

когда FMT заменяется соответствующей строкой. Этот подход может оказаться очень удобным, если есть длинная строка, которую мы используем несколько раз. В следующей строке программы MSG заменяется соответствующей строкой. Кавычки делают замещающую строку константой символьной строки. Поскольку программа получает ее содержимое, эта строка будет запоминаться в массиве, заканчивающемся нуль-символом. Так,

#define HAL 'X' определяет символьную константу, а

#define HAR "X" определяет символьную строку X\0

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

printf("TWO: MSG");

печатает буквально TWO: MSG вместо печати следующего текста:

2: "Текст 1.

Продолжение текста 1"

Если нам нужно напечатать этот текст, можно использовать оператор

printf("%d: %s\n",TWO,MSG);

потому что здесь макроопределения находятся вне кавычек.

Когда следует использовать символические константы? Вероятно, мы должны применять их для большинства чисел. Если число является константой, используемой в вычислениях, то символическое имя делает яснее ее смысл. Если число - размер массива, то символическое имя упрощает изменение вашей программы при работе с большим массивом. Если число является системным кодом, скажем для символа EOF, то символическое представление делает программу более переносимой. Изменяется только определение EOF. Мнемоническое значение, легкость изменения, переносимость: все это делает символические константы заслуживающими внимания!