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

на главную - закладки

Жанры

Освой самостоятельно С++ за 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 а)

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

Плохой парень, Купидон и я

Уильямс Хасти
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Плохой парень, Купидон и я

Кротовский, сколько можно?

Парсиев Дмитрий
5. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Кротовский, сколько можно?

Адвокат вольного города 5

Кулабухов Тимофей
5. Адвокат
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Адвокат вольного города 5

Лекарь для захватчика

Романова Елена
Фантастика:
попаданцы
историческое фэнтези
фэнтези
5.00
рейтинг книги
Лекарь для захватчика

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

Миф об идеальном мужчине

Устинова Татьяна Витальевна
Детективы:
прочие детективы
9.23
рейтинг книги
Миф об идеальном мужчине

Рота Его Величества

Дроздов Анатолий Федорович
Новые герои
Фантастика:
боевая фантастика
8.55
рейтинг книги
Рота Его Величества

С Д. Том 16

Клеванский Кирилл Сергеевич
16. Сердце дракона
Фантастика:
боевая фантастика
6.94
рейтинг книги
С Д. Том 16

Венецианский купец

Распопов Дмитрий Викторович
1. Венецианский купец
Фантастика:
фэнтези
героическая фантастика
альтернативная история
7.31
рейтинг книги
Венецианский купец

Лейб-хирург

Дроздов Анатолий Федорович
2. Зауряд-врач
Фантастика:
альтернативная история
7.34
рейтинг книги
Лейб-хирург

Барон диктует правила

Ренгач Евгений
4. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон диктует правила

Завод 2: назад в СССР

Гуров Валерий Александрович
2. Завод
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Завод 2: назад в СССР

Кодекс Охотника. Книга XVIII

Винокуров Юрий
18. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVIII

Неудержимый. Книга IX

Боярский Андрей
9. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга IX