Все разделы
Выбрать школу

Школа. Увлечения. Большое будущее.

PROSCHOOLS · ОБРАЗОВАНИЕ РЯДОМ

Ваш город

Выберите город, чтобы находить образование и возможности рядом.

Как учитываем городКаталог и кнопки «Выбрать школу» покажут школы выбранного города.Онлайн-курсы, учебник, ГДЗ и задания к экзаменам доступны по всей России.

Популярные города

Будет выбран: Вся Россия

Учебные материалы останутся прежними.

Поиск по сайту

По всему сайтуШколы выбранного города — выше в результатах

С чего начнём?

↑ ↓ — выбрать результат · Enter — открыть · Esc — закрыть

Макросы препроцессора C: подстановка текста и типичные ловушки

💻 Информатика · 11 класс

Макрос в языке C — именованный фрагмент, который препроцессор подставляет вместо использования имени. Он обрабатывается до обычного анализа программы компилятором и не обладает все

Клавиатура в компьютерном классе
Иллюстрация к предмету «Информатика»Hmartil · Wikimedia Commons · CC BY-SA 4.0

Макрос в языке C — именованный фрагмент, который препроцессор подставляет вместо использования имени. Он обрабатывается до обычного анализа программы компилятором и не обладает всеми свойствами функции. Поэтому одинаково выглядящие записи вызова макроса и функции могут вести себя по-разному.

Объектный макрос

Пример #define LIMIT 8 задаёт замену имени LIMIT на последовательность токенов 8. После этого запись int a[LIMIT]; будет обработана с числом вместо имени. Точка с запятой в определение числового макроса обычно не включается: она стала бы частью подстановки и могла бы нарушить выражение.

Макрос не является переменной и не занимает память как отдельный объект только благодаря своему объявлению. У него также нет обычного типа переменной. Если задача решается константой или функцией языка, следует рассмотреть такой вариант: он часто лучше проверяется компилятором. Макрос нужен там, где действительно требуется работа препроцессора.

Макрос с параметром

Опасная запись #define SQUARE(x) x*x при использовании SQUARE(1+2) разворачивается в 1+2*1+2. По приоритетам это 5, а не 9. Скобки вокруг параметров и всего результата уменьшают этот риск: #define SQUARE(x) ((x)*(x)).

Но скобки не превращают макрос в функцию. Для SQUARE(i++) выражение увеличения оказывается в подстановке дважды. Это пример того, почему аргументы с побочными эффектами опасны; не нужно экспериментально подбирать «правильное число», поскольку поведение таких выражений зависит от правил вычисления и может быть неопределённым. Передайте заранее вычисленное значение либо используйте функцию.

Как читать ошибку

Мысленно выполните подстановку, сохранив все операторы и скобки. Затем отдельно примените правила языка C к полученному выражению. Такое двухэтапное чтение позволяет понять, где ошибка: в определении макроса или в предположении о порядке вычисления. Не используйте макрос для скрытого изменения нескольких несвязанных переменных.

В небольшом учебном проекте полезно держать макросы короткими, давать им различимые имена и проверять неожиданные аргументы: сумму, отрицательное значение, выражение с вызовом. Это не заменяет понимание семантики, но быстро выявляет наивные определения.

Практика с ответами

1. Почему #define N 4; отличается от #define N 4? Точка с запятой тоже попадёт в замену. 2. Чему равно SQUARE(2+3) для определения без скобок? Выражение 2+3*2+3 равно 11. 3. Устраняет ли версия ((x)*(x)) все риски? Нет: повторное вычисление аргумента сохраняется.

Для закрепления замените такой макрос обычной функцией, принимающей целое число. Объясните, какие проверки выполняет компилятор и сколько раз вычисляется выражение аргумента при вызове. Сравнение должно учитывать смысл, а не только краткость записи.

Связанные материалы

Начала программирования, Что такое алгоритм.

Источники и проверка

GCC: Macros; GCC: Macro Pitfalls.

Источники и материалы