Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Либерти Джесс. Освой самостоятельно С++ за 21 день. - royallib.ru.rtf
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
2.55 Mб
Скачать

Макросы

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

#define TWICE(x) ( (x) * 2 )

А затем в программе можно записать следующую строку:

TWICE(4)

Целая строка TWICE(4) будет удалена, а вместо нее будет стоять значение 8! Когда препроцессор считывает параметр 4, он выполняет следующую подстановку: ((4) * 2), это выражение затем вычисляется как 4 * 2 и в результате получается число 8.

Макрос может иметь больше одного параметра, причем каждый параметр в тексте замены может использоваться неоднократно. Вот как можно определить два часто используемых макроса — МАХ и MIN:

#define MAX(x,y) ( (x) > (у) ? (x) : (у) )

#define MIN(x,y) ( (x) < (у) ? (x) : (у) )

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

#define MAX (x,y) ( (x) > (у) ? (x) : (у) )

и попытаться использовать макрос МАХ

int x = 5, у = 7, z;

z = MAX(x,y);

то промежуточный код будет иметь следующий вид:

int x = 5, у = 7, z;

z = (x,y) ( (x) > (у) ? (x) : (у) )(x,y)

В этом случае сделана простая текстовая замена, а не вызов макроса, т.е. лексема МАХ была заменена выражением (x,y) ( (x) > (у) ? (x) : (у) ),за которым сохранилась строка (x, у).

Однако после удаления пробела между словом МАХ и списком параметров (x,y) промежуточный код выглядит уже по-другому:

int x = 5, у = 7, z;

z =7;

Зачем нужны все эти круглые скобки

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

#define MAX(x,y) x > у ? x : у

и передать значения 5 и 7, то макрос МАХ будет нормально работать. Но если передать более сложные выражения, можно получить неожиданные результаты, как показано в листинге 21.2.

Листинг 21.2. Использование в макросе круглых скобок

1: // Листинг 21.2. Использование в макросе круглых скобок

2: #include <iostream.h>

3:

4: #define CUBE(a) ( (а) * (а) << (а) )

5: #define THREE(a) а * а * а 6:

7: int main()

8: {

9:    long x = 5;

10:   long у = CUBE(x);

11:   long z = THREE(x);

12:

13:   cout << "у: " << у << endl;

14:   cout << "z: " << z << endl;

15:

16:   long а = 5, b = 7;

17:   у = CUBE(a+b);

18:   z = THREE(a+b);

19:

20:   cout << "у: " << у << endl;

21:   cout << "z: " << z << endl;

22:   return 0;

23: }

Результат:

у: 125

z: 125

у: 1728

z: 82

Анализ: В строке 4 определяется макрос CUBE с параметром x, который заключается в круглые скобки при каждом его использовании в выражении. В строке 5 определяется макрос THREE, параметр которого используется без круглых скобок.

При первом использовании этих макросов параметру передается значение 5, и оба макроса прекрасно справляются со своей работой. Макрос CUBE(5) преобразуется в выражение ( (5) * (5) * (5) ), которое при вычислении дает значение 125, а макрос THREE(5) преобразуется в выражение 5 * 5 * 5, которое также возвращает значение 125.

При повторном обращении к этим макросам в строках 16—18 параметру передается выражение 5 + 7. В этом случае макрос CUBE(5+7) преобразуется в следующее выражение:

( (5+7) * (5+7) * (5+7) )

Оно соответствует выражению

( (12) * (12) * (12) )

При вычислении этого выражения получаем значение 1728. Однако макрос THREE(5+7) преобразуется в выражение иного вида:

5 + 7 * 5 + 7 * 5 + 7

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

5 + (7 * 5) + (7 * 5) + 7

После вычисления произведений в круглых скобках получаем выражение

5 + (35) + (35) + 7

После суммирования оно возвращает значение 82.