Учись программированию на C++ Builder бесплатно!

Формат директивы #define, определяющей макрос с параметрами:

#define идентификатор_макроса(аргументы) замещающий_текст

Между идентификатором макроса и открывающейся скобкой не должно быть пробела. Вызов макроса осуществляется выражением:

идентификатор_макроса(аргументы)

Макрос, определяемый директивой препроцессора #define, это символическое имя некоторых операций. Как и в случае символических констант, идентификатор макроса заменяется на замещающий текст до начала компиляции программы. Но сначала в замещающий текст подставляются значения параметров, а затем уже этот расширенный макрос подставляется в текст вместо идентификатора макроса и списка его параметров.

Например, следующий макрос с одним параметром определяет площадь круга, воспринимая передаваемый в него параметр как радиус:

#define CIRC(x) (3.14159*(x)*(x))

Везде в тексте файла, где появится идентификатор CIRC(А), значение аргумента А будет использовано для замены x в замещающем тексте и этот расширенный текст макроса будет использован для замещения. Например, оператор с макросом: в тексте программы примет вид:

S = CIRC(4);
S = (3.14159*(4)*(4));

Поскольку это выражение состоит только из констант, его значение будет вычислено во время компиляции и полученный результат будет присвоен переменкой S во время выполнения программы. Если вызов имеет вид:

S = CIRC (a + b);

то после расширения макроса текст будет иметь вид:

S = (3.14159 * (а + b) * (а + b));

В данном случае аргумент макроса является выражением, содержащим переменные а и b. Поэтому вычисления будет осуществляться не во время компиляции, а во время выполнения программы.

Обратите внимание на круглые скобки вокруг каждого включения параметра x в тексте рассмотренного макроса и вокруг всего выражения. При вызове типа CIRC(4) они кажутся излишними.

Вызов функции сопряжен с накладными расходами и затягивает выполнение программы. Это соображение работает в пользу использования макросов. С другой стороны, макрос расширяется во всех местах текста, где используется его вызов. Если таких мест в программе много, то это увеличивает размер текста и, соответственно, размер выполняемого модуля. Так что функции позволяют сокращать объем выполняемого файла, а макросы - сокращать скорость выполнения. Правда, макросы тоже могут быть связаны с дополнительными накладными расходами.

В приведенном примере значение параметра а + b вычисляется дважды, в то время как в функции это вычисление осуществляется только один раз. Конечно, для таких простых вычислений это не существенно. Но если в качестве параметра передается сложное выражение, обращающееся в свою очередь к каким-нибудь сложным функциям, то эти дополнительные накладные расходы могут стать заметными и затянуть вычисления.

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

Поделиться