Как видите, многие предопределенные макросы C++Builder отражают те или иные установки параметров компиляции, задаваемые в командной строке (при ручном запуске компилятора Ьсс32.ехе). Те же самые установки могут быть выполнены и в интегрированной среде через диалог Project Options, который мы еще будем рассматривать в этой главе.
Макросы с параметрами
Макросы могут выполнять не только простую текстовую подстановку. Возможно определение макросов с параметрами, напоминающих функции языка С, например:
#define PI 3.14159265
#define SQR(x) ( (x) * (x) )
#define AREA(x) (PI * SQR(x))
#define MAX(a, b) (<a)>(b) ? (a): (b))
…
circleArea = AREAfrl + r2);
cMax = MAX(i++, j++);
Третье макроопределение показывает, что макросы могут быть вложенными. После каждого расширения макроса препроцессор снова сканирует полученный текст на предмет того, не содержит ли он идентификаторов, в свою очередь являющихся макросами. Исключением являются случаи, когда расширение содержит собственное имя макроса или является препроцессорной директивой.
Обратите внимание на скобки в показанных 'выше определениях. Можно сформулировать такое правило: каждый параметр и все определение в целом должны заключаться в скобки. Иначе при вхождении макроса в выражение могут появляться ошибки, связанные с различным приоритетом операций. Рассмотрите такой случай:
#define SQR(x) х*х binom = -SQR(a + b) ;
При расширении макроса получится:
binom = -a + b*a + b;
Порядок оценки выражения окажется совсем не тем, что подразумевался.
Преобразование в строку
В макросах может применяться специальная операция преобразования в строку (#). Если в расширении макроса параметру предшествует эта опе-
рация, то выражение-аргумент будет преобразовано в литеральную строку, заключенную в двойные кавычки. Вот один пример:
#define SHOWINT(var)
printf(#var " = %d\n", (int)(var))
int iVariable = 100;
SHOWINT(iVariable) ;
Последняя строчка расширяется в
printf("iVariable"" = %d\n", (int)(iVariable));
и печатает
iVariable = 100
В С примыкающие друг к другу литеральные строки при компиляции соединяются в одну строку.
Конкатенация
Операция конкатенации (##) позволяет составить из нескольких лексем единое слово. Получившийся элемент повторно сканируется для обнаружения возможного идентификатора макроса. Рассмотрите такой код:
#define DEF_INT(n) int iVar ## n
…
DEF_INT(One); // Расширяется в int iVarOne;
DEF_INT(Two); // Расширяется в int iVarTwo; и т.д.