Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
13
Добавлен:
17.04.2015
Размер:
34.77 Кб
Скачать

7. Примеры констант.

1.Это типичный пример использования #define (как минимум в C):

#define TRUE 1

#define FALSE 0

...

int done = 0;

while( done != TRUE ) {

...

}

2. Например, если необходимо использовать TRUE для значения 1, a FALSE для 0 то можно объявить следующие два макроса:

#define TRUE 1

#define FALSE 0

В результате, если компилятор обнаружит в тексте программы TRUE или FALSE, то он заменит их на 1 и 0 соответственно. Например, следующая строка выводит на экран «0 1 2»:

printf ("%d %d %d", FALSE, TRUE, TRUE + 1);

3. В случае, если макрос определен, он может использоваться для определения других макросов. Например, следующий код сопоставляет с именами ONE, TWO и THREE их численные значения:

#define ONE 1

#define TWO ONE + ONE

#def ine THREE ONE + TWO

В результате макроподстановки идентификаторы замещаются указанными строками.

4. Если не­обходимо определить стандартное сообщение об ошибке, то можно написать что-то вроде следующего:

#define E_MS "Standart error on input.\n"

/*...*/

printf(E_MS);

Если компилятор обнаруживает идентификатор E_MS, то он замещает его строкой «Standart error on input.» На самом деле компилятор увидит оператор в виде

printf("Standart error on input.\n");

5. Если идентификатор находится в строке, то подстановка не происходит. Например:

#define XYZ this is a test

/*...*/

printf("XYZ");

выведет не «this is a test», a «XYZ».

6. Если строка не вмещается в одной строке, то ее можно продолжить на следующей строке, поместив в конце строки обратный слэш, как показано в следующем примере:

#define LONG_STRING "This is a very long" \

string that is used as an example."

7. Директива препроцессора

#define PI 3.14159

Превращает корректное объявление

float PI;

в синтаксически некорректную конструкцию

float 3.14159;

А следующее определение правильное.

float pi = PI;

После препроцессирования оно принимает такой вид:

float pi = 3.14159;

Сначала препроцессор замещает, затем транслятор транслирует. И потому здесь будет зафиксирована ошибка:

#define PI 3.14 0.00159

float pi = PI;

После препроцессирования объявление принимает такой вид:

float pi = 3.14 0.00159;

А здесь - всё корректно:

#define PI 3.14 + 0.00159

float pi = PI;

После препроцессирования получается правильное объявление с инициализацией:

float pi = 3.14 + 0.00159;

8. Строка замещения может оказаться пустой.

#define ZZZ

В этом случае оператор-выражение

ZZZ;

и ещё более странные конструкции

ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ;

превращаются препроцессором в пустой оператор. Это лишь побочный эффект работы препроцессора. У макроопределений с пустой строкой замещения имеется собственная область пременения.

9.Многострочные макрокоманды и константы

Строка замещения может располагаться на нескольких строках. При этом символ '\' уведомляет препроцессор о необходимости включения в состав строки замещения текста, располагаемого на следующей стоке. Признаком завершения многострочного определения является символ конца строки:

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

#define TEXT "1234567890-=\

йцукенгшщзхъ\"

В ходе препроцессорной обработки вхождения идентификатора TEXT заменяются на строку замещения:

1234567890-= йцукенгшщзхъ\

#define very_long_character_string " Эта строковая константа\

требует две строки"

#define _toupper(c) ((((с) >= 'а') && ((с) <= 'z'))\

? (с) - 'а' + 'А' : с)

10.Макроопределения define могут быть вложенными:

#include <iostream.h>

#define WHISKEY "ВИСКИ с содовой."

#define MARTINI "МАРТИНИ со льдом и " WHISKEY

void main() {cout << MARTINI;}

В результате выполнения последнего оператора выводится строка

МАРТИНИ со льдом и ВИСКИ с содовой.

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

Так что макроопределение

#define WHISKEY "стаканчик ВИСКИ " WHISKEY

обречено на неудачу.

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

#undef ИмяЗамещаемойЧасти

Эта инструкция прекращает действие препроцессора по замене соответствующего идентификатора.

#define PI 3.14 + 0.00159

float pi1 = PI;

#undef PI

#define PI 3.14159

float pi2 = PI;

12. Операция ##. Конкатенация в макроопределениях

В следующем примере мы используем ещё одну специальную операцию для управленияпрепроцессором - операцию конкатенации ##. Обычно эта операция используется в контексте функциональных макроопределений.

Если в замещающей последовательности лексем между двумя лексемами встречается операция препроцессирования## и, возможно, что одна или обе лексемы являются параметрами, то препроцессор вначале обеспечивает подстановку фактических значений в параметры, после чего сама операция конкатенации и окружающие её пробельные символы убираются:

#include <iostream.h>

#define XXX(YYY) "МАРТИНИ со льдом и" ## YYY void main() { cout << XXX("ВИСКИ с содовой") << endl; cout << XXX("на сегодня достаточно…") << endl; // Для препроцессора тип параметра не имеет значения. // Важно, как посмотрит на это транслятор… cout << XXX(255); }

Перед нами ещё одно мощное и изящное средство управления препроцессором.

13. Следует иметь в виду, что препроцессор не выполняет проверки синтаксической правильности текста подстановки, поэтому использование конструкции

#define PI = 3.1415

приведет к тому, что вместо идентификатораPI везде будет подставляться текст "= 3.1415", что явно не соответствует желаемому. Ошибка будет обнаружена только на этапе компиляции.