1.14. Макроопределения

Макроопределения задаются, подобно символическим константам (которые являются простейшими макроопределениями), директивой препроцессора #(1еппе в виде:

#(1еппе имя ( список параметров ) строка замещения где имя - некоторый идентификатор, список параметров - список идентификато­ров, разделенных запятыми, строка замещения - это, как правило, некоторое вы­ражение или последовательность операторов, куда входят параметры, указанные в скобках. В программе макроопределения, подобно функциям, используются со списком аргументов (аргументами могут быть любые правильно записанные вы­ражения). Препроцессор проделывает с встреченными им в тексте программы макроопределениями следующие манипуляции :

1) каждое вхождение параметра в строку замещения заменяется на соответ­ствующий аргумент (если только параметр в строке замещения не находится внутри " ");

2) параметры, предваряемые символом # в строке замещения макроопреде­ления, заменяются на соответствующий аргумент в " ";

3) подготовленная таким образом строка замещения подставляется в текст программы.

В отличие от функций, предварительного вычисления значений аргументов не происходит, все операции выполняются только над текстом. В качестве при­мера запишем макроопределение       для вычисления квадрата числа :

#11еГте 8((Щх) ((х)*(х)) и макроопределение, предоставляющее удобное средство отладочной печати:

#11еГте ОШТиТ(х,Г) рпп1Г("\п"#х"=0/о"#Г,(х)) Отметим, что использование макроопределений иногда приводит к побочным эффектам, которые возникают при многократном использовании аргументов-выражений. Например, т1 х=2; у=8((Щх++); В результате выражение х++ * х++ установит х в 4 вместо 3, а у в 6=2*3 вместо ожидаемого значения 4. Кроме того, текстовые подстановки не позволяют применять в качестве аргументов арифме­тические выражения, поскольку они вычисляются в теле макроподстановки мно­гократно, что замедляет выполнение программы. Еще один недостаток макрооп­ределений - невозможность отличить вызовы функций от вызовов макроопреде­лений в тексте программы.

В языке C++ существует возможность вставки фрагмента кода (а не текста) функции, чтобы не выполнять переход к коду функции при ее вызове. Для этого перед описанием функции ставится ключевое слово inline. Например, inline int sqr(int x) {return x*x;} Наиболее эффективно использовать подставляемые функции в тех случаях, когда тело функции состоит всего из нескольких опера­торов, хотя при многократных вызовах подставляемой функции размеры про­граммы могут увеличиться, однако исключаются затраты на передачу управле­ния к вызываемой функции и возврат из нее. Так как компилятор встраивает код подставляемой функции вместо ее вызова, то определение функции со специфи­катором inline должно находиться в том же файле, что и обращение к ней, и раз­мещаться до первого вызова. Функция со спецификатором inline не может быть рекурсивной и не может содержать операторов goto , switch , do , for , while.