Link: Лекция 11: Препроцессор языка Си

Т.к. C является компилируемым языком, а не интерпретируемым (как PHP или JavaScript) или смесь того и другого (Java), не лишним будет знать как работает компилятор, что при этом происходит. Не люблю магию в программировании:

Общие сведения

  1. Все системно-зависимые обозначения перекодируются в стандартные коды.
  2. Каждая пара из символов ‘ \ ‘ и “конец строки” вместе с пробелами между ними убираются, и тем самым следующая строка исходного текста присоединяется к строке, в которой находилась эта пара символов.
  3. В тексте распознаются директивы и лексемы препроцессора, а каждый комментарий заменяется одним символом пустого промежутка.
  4. Выполняются директивы препроцессора и производятся макроподстановки.
  5. Эскейп-последовательности в символьных константах и символьных строках заменяются на их эквиваленты.
  6. Смежные символьные строки конкатенируются, то есть соединяются в одну строку.
  7. Каждая препроцессорная лексема преобразуется в текст на языке Си.

Символические константы: #define

#define – директива препроцессора. Может появится в любом месте файла, а даваемое определение имеет силу от места появления до конца файла.

Очень напоминает define для PHP. Только в отличии от него, кроме константы, может определять целые “функции”, но об этом ниже, а пока пример

А теперь кое-что поинтереснее

Не переключайтесь, дальше будет еще интереснее

Главное, что Вы должны запомнить, препроцессор не выполняет вычислений. Скоро вы поймете все важность этой фразы

Использование аргументов с #define

Во избежание ошибок при вычислении выражений параметры макроопределения необходимо заключать в скобки.

Макроопределения с аргументами очень похоже на функцию, но есть одно важное отличие:

Честно говоря, для меня это был шок.

Давайте разберемся с 3 строкой шаг за шагом:

В случае x=4, мы получаем 4*4. Все понятно, как мы и ожидали.

Но когда дело доходит до x+2, и мы ожидаем 6*6, препроцессор удивляет нас. На выходе мы получаем x+2*x+2. Т.е. он ничего не перемножает, а просто заменяет. Для него не существует приоритетов операторов. И на выходе мы получаем 4+2*4+2=14 (вот откуда берется 14)

Точно также и с остальными выражениями

 

Описать я это описал, но повторить не смог (в качестве компилятора я использовал продукт jetBrains – CLion) и у меня получились следующие результаты:

Макроопределение или функция?

Я бы не стал слишком сильно полагаться на макроопределения с аргументами. Слишком уж не заметные побочные эффекты.

Включение файла: #include

Расскажу на примерах

Условная компиляция

Вспомогательные директивы

Реакция на ошибки

Прагмы

Эта директива определяет действия, зависящие от конкретной реализации компилятора. Думаю этой фразы достаточно.

Встроенные макроимена

[toggles class=”yourcustomclass”]
[toggle title=”Отметьте правильные варианты включения файлов в код программы?”]

  • #include “nina.h”
  • #include “stdio.h”
  • #include <stdio.h>
  • #include “a:nina.h”

[/toggle]

[toggle title=”Имеется следующее объявление: int x, j = 1;. Какой вариант макроопределения приведет к ответу 9 в результате вызова x = NEW(j << 2);?”]

#define NEW(X) ((X)+5)

[/toggle]
[toggle title=”В чем опасность применения макрофункций?”]

побочный эффект

[/toggle]
[toggle title=”Где может появиться директива #define?”]

  • под командами включения файлов
  • в начале файла
  • в середине файла
  • в конце файла

[/toggle]

[toggle title=”Из каких стадий состоит препроцессорная обработка?”]

  • выполняются директивы препроцессора и производятся макроподстановки
  • в тексте распознаются директивы и лексемы препроцессора, а каждый комментарий заменяется одним символом пустого промежутка
  • все системно-зависимые обозначения перекодируются в стандартные коды
  • каждая пара из символов ‘\’ и “конец строки” вместе с пробелами между ними убираются, и тем самым следующая строка исходного текста присоединяется к строке, в которой находилась эта пара символов

[/toggle]

[toggle title=”Какие утверждения верны?”]

  • препроцессор не выполняет вычисления
  • препроцессор делает предложенные подстановки

[/toggle]

[toggle title=”Какая макрофункция печатает значения двух целых выражений?”]

#define P(X,Y) printf(“X=%d, Y=%d.\n”,X,Y)

[/toggle]

[/toggles]