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

на главную

Жанры

Освой самостоятельно С++ за 21 день.

Либерти Джесс

Шрифт:

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.

Макросы в сравнении с функциями шаблонов

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

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

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

Однако наиболее существенна последняя проблема: в макросах не поддерживается контроль за соответствием типов данных. Хотя возможность использования в макросе абсолютно любого параметра кажется удобной, этот факт полностью подрывает строгий контроль типов в C++ и является проклятием для программистов на C++. Конечно, существует корректный способ решить и эту проблему — нужно воспользоваться услугами шаблонов, как было показано на занятии 19.

Подставляемые функции

Часто вместо макросов удобно объявить подставляемую функцию. Например, в листинге 21.3 создается функция CUBE, которая выполняет ту же работу, что и макрос CUBE в листинге 21.2, но в данном случае это делается способом, обеспечивающим контроль за соответствием типов.

Листинг 21.3. Использование подставляемой функции вместо макроса

1: #include <iostream.h>

2:

3: inline unsigned long Square(unsigncd long а) { return а * а; }

4: inline unsigned long Cubo(unsigned long а)

Поделиться:
Популярные книги

Виконт. Книга 1. Второе рождение

Юллем Евгений
1. Псевдоним `Испанец`
Фантастика:
фэнтези
боевая фантастика
попаданцы
6.67
рейтинг книги
Виконт. Книга 1. Второе рождение

Последний попаданец 3

Зубов Константин
3. Последний попаданец
Фантастика:
фэнтези
юмористическое фэнтези
рпг
5.00
рейтинг книги
Последний попаданец 3

Не грози Дубровскому! Том Х

Панарин Антон
10. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том Х

Я до сих пор не князь. Книга XVI

Дрейк Сириус
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я до сих пор не князь. Книга XVI

Мастер Разума III

Кронос Александр
3. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.25
рейтинг книги
Мастер Разума III

Горькие ягодки

Вайз Мариэлла
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Горькие ягодки

Расческа для лысого

Зайцева Мария
Любовные романы:
современные любовные романы
эро литература
8.52
рейтинг книги
Расческа для лысого

Счастье быть нужным

Арниева Юлия
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Счастье быть нужным

Треск штанов

Ланцов Михаил Алексеевич
6. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Треск штанов

Титан империи 2

Артемов Александр Александрович
2. Титан Империи
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Титан империи 2

Законы Рода. Том 5

Flow Ascold
5. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 5

Иван Московский. Первые шаги

Ланцов Михаил Алексеевич
1. Иван Московский
Фантастика:
героическая фантастика
альтернативная история
5.67
рейтинг книги
Иван Московский. Первые шаги

Пятое правило дворянина

Герда Александр
5. Истинный дворянин
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Пятое правило дворянина

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3