
- •Содержание
- •Лабораторная работа №9 классы хранения и видимость переменных
- •Теоретические сведения
- •Варианты индивидуальных заданий
- •Приложение 1
- •Лабораторная работа №10 препроцессорные средства
- •Теоретические сведения
- •1. Состав директив препроцессора и стадии препроцессорной обработки
- •2. Стадии препроцессорной обработки
- •3. Замены в тексте программы
- •4. Цепочка подстановок
- •5. Включение текстов из файлов
- •6. Условная компиляция
- •7. Операция defined
- •8. Макроподстановки средствами препроцессора
- •9. Моделирование многомерных массивов
- •10. Отличия макросов от функций
- •11. Препроцессорные операции в строке замещения
- •12. Вспомогательные директивы
- •13. Реакция на ошибки
- •14. Пустая директива
- •15. Встроенные (заранее определенные) макроимена
- •Варианты индивидуальных заданий
- •Лабораторная работа № 11 динамическое распределение памяти
- •Теоретические сведения
- •1. Функции malloc и free
- •2. Операторы new и delete
- •Варианты индивидуальных заданий
- •Лабораторная работа № 12 структура данных «список»
- •Теоретические сведения
- •1. Основные определения
- •2. Операции над списками
- •3. Пример реализации односвязного списка с помощью массива структур
- •4. Пример реализации двусвязного списка с помощью массива данных
- •Варианты индивидуальных заданий
- •Лабораторная работа №13 очереди. Операции над очередями. Деки
- •Теоретические сведения
- •1. Понятие очереди. Операции над очередями. Кольцевая очередь. Дек
- •2. Программная реализация очереди на основе массива
- •Варианты индивидуальных заданий
- •Лабораторная работа №14 стеки. Очереди. Операции над стеками и очередями
- •Теоретические сведения
- •1. Понятие стека. Операции над стеком
- •2. Программная реализация стека на основе массива
- •Варианты индивидуальных заданий
- •Лабораторная работа №15
- •Анализ пузырьковой сортировки. Пузырьковая сортировка обладает несколькими характеристиками:
- •2. Сортировка методом выбора
- •3. Сортировка методом вставки
- •4. Сортировка методом Шелла
- •5. Сортировка методом Хоора
- •6. Алгоритмы поиска
- •Варианты индивидуальных заданий
- •Приложение 2
- •Лабораторная работа №16 программирование алгоритмов вычислительной математики
- •Теоретические сведения
- •1. Методы Симпсона
- •Варианты индивидуальных заданий
- •Литература
10. Отличия макросов от функций
Сравнивая макросы с функциями, заметим, что в отличие от функции, определение которой всегда присутствует в одном экземпляре, тексты, формируемые макросом, вставляются в программу столько раз, сколько раз используется макрос. Обратим внимание на еще одно отличие: функция определена для данных того типа, который указан в спецификации ее параметров и возвращает значение только одного конкретного типа. Макрос пригоден для обработки параметров любого типа, допустимых в выражениях, формируемых при обработке строки замещения. Тип получаемого значения зависит только от типов параметров и от самих выражений. Таким образом, макрос может заменять несколько функций. Например, приведенные выше макросы mах() и ABS() верно работают для параметров любых целых и вещественных типов, а результат зависит только от типов параметров.
Для устранения неоднозначных или неверных использований макроподстановок параметры в строке замещения и ее саму полезно заключать в скобки. Еще одно отличие: фактические параметры функций – это выражения, а аргументы вызова макроса – препроцессорные лексемы, разделенные запятыми. Аргументы макрорасширениям не подвергаются.
11. Препроцессорные операции в строке замещения
В последовательности лексем, образующей строку замещения, предусматривается использование двух операций – ‘#’ и ‘##’, первая из которых помещается перед параметром, а вторая – между любыми двумя лексемами. Операция ‘#’ требует, чтобы текст, замещающий данный параметр в формируемой строке, заключался в двойные кавычки.
В качестве полезного примера с операцией ‘#’ рассмотрим следующее макроопределение:
#define print (A) printf (#A”=%f”, А)
К макросу print (А) можно обращаться, подставляя вместо параметра А произвольные выражения, формирующие результаты вещественного типа.
Пример 10.18
print (sin (a/2)); – обращение к макросу;
printf (“sin (a/2)””=%f”, sin (a/2)); – макрорасширение.
Фрагмент программы:
double а=3.14159;
print (sin (a/2));
Результат выполнения (на экране дисплея):
sin (a/2)=1.0
Операция ‘##’, допускаемая только между лексемами строки замещения, позволяет выполнять конкатенацию лексем, включаемых в строку замещения.
Чтобы пояснить роль и место операции ‘##’, рассмотрим, как будут выполняться макроподстановки в следующих трех макроопределениях с одинаковым списком параметров и одинаковыми аргументами.
Пример 10.19
#define zero (a, b, с, d) a (bcd)
#define one (a, b, c, d) a (b с d)
#define two (a, b, c, d) a (b##c##d)
Макровызов: Результат макроподстановки:
zero(sin, x, +, у) sin(bcd)
one (sin, x, +, у) sin(x + у)
two(sin, x, +, y) sin(x+y)
В случае zero() последовательность “bcd” воспринимается как отдельный идентификатор. Замена параметров b, с, d не выполнена. В строке замещения макроса оnе() аргументы отделены пробелами, которые сохраняются в результате. В строке замещения для макроса two() использована операция ‘##’, что позволило выполнить конкатенацию аргументов без пробелов между ними.