Язык программирования Си для персонального компьютера | страница 114
Выше уже говорилось, что макроопределение может содержать более одного вхождения данного формального параметра. Если формальный параметр представлен выражением с побочным эффектом, то это выражение будет вычисляться более одного раза, а вместе с ним каждый раз будет возникать и побочный эффект. Результат выполнения в этом случае может быть ошибочным.
Внутрь <текста> в директиве #define могут быть вложены имена других макроопределений или констант. Их расширение производится лишь при расширении <идентификатора> этого <текста>, а не при его определении директивой #define. Это надо учитывать, в частности, при взаимодействии вложенных именованных констант и макроопределений с директивой #undef: к моменту расширения содержащего их текста они могут уже оказаться отменены директивой #undef.
После того как выполнена макроподстановка, полученная строка вновь просматривается для поиска других имен констант и макроопределений. При повторном просмотре не принимается к рассмотрению имя ранее произведенной макроподстановки. Поэтому директива
#define х х
не приведет к зацикливанию препроцессора.
Примеры.
/* пример 1 */
#define WIDTH 80
#define LENGTH (WIDTH + 10)
/* пример 2 */
#define FILEMESSAGE "Попытка создать файл\
не удалась из-за нехватки дискового пространства"
/* пример 3 */
#define REG1 register
#define REG2 register
#define REG3
/* пример 4 */
#define MAX(x, y)((x)>(у)) ? (x) : (у)
/* пример 5 */
#define MULT(a, b) ((a)*(b))
В первом примере идентификатор WIDTH определяется как целая константа со значением 80, а идентификатор LENGTH — как текст (WIDTH + 10). Каждое вхождение идентификатора LENGTH в исходный файл будет заменено на текст (WIDTH + 10), который после расширения идентификатора WIDTH превратится в выражение (80 + 10). Скобки, окружающие текст (WIDTH + 10), позволяют избежать ошибок в операторах, подобных следующему:
var = LENGTH * 20;
После обработки препроцессором оператор примет вид:
var = (80 + 10)* 20;
Значение, которое присваивается var, равно 1800. В отсутствие скобок в макроопределении оператор имел бы следующий вид:
var = 80 + 10*20;
Значение var равнялось бы 280, поскольку операция умножения имеет более высокий приоритет, чем операция сложения.
Во втором примере определяется идентификатор FILEMESSAGE. Его определение продолжается на вторую строку путем использования символа обратный слэш непосредственно перед нажатием клавиши ENTER.
В третьем примере определены три идентификатора, REG1, REG2, REG3. Идентификаторы REG1 и REG2 определены как ключевые слова