Каждая из последующих программ начинается с оператора препроцессора:
#include "defs.h"
Препроцессор заменяет приведенную выше строку на содержимое файла defs.h, что делает определения, содержащиеся в файле defs.h, доступными для использования. Ниже приводится содержимое defs.h.
#include <stdio.h> #define PR(format,value) printf("value = %format\t",value) #define NL putchar('\n') #define PRINT1(f,x1) PR(f,x1);NL #define PRINT2(f,x1,x2) PR(f,x1);PRINT1(f,x2) #define PRINT3(f,x1,x2,x3) PR(f,x1);PRINT2(f,x2,x3) #define PRINT4(f,x1,x2,x3,x4) PR(f,x1);PRINT3(f,x2,x3,x4)
Файл defs.h, в свою очередь, опять начинается с оператора include, требующего поместить в программу содержимое файла stdio.h, что необходимо для пользования библиотекой стандартных программ С. Оставшаяся часть файла defs.h содержит макроопределения для печати. Например, чтобы напечатать 5, как целое десятичное число, нужно обратиться к PRINT1 следующим образом:
PRINT1(d,5)
это обращение заменяется на
PR(d,5);NL
что дальше заменяется на
printf("5 = %d\t",(5)); putchar('\n')
Макроопределение PRINT1 показывает некоторую особенность препроцессора, которая часто приводит к неприятностям. Если определяемое имя встречается внутри строки, т.е. между двумя двойными кавычками, то оно не заменяется. Однако, аргументы макроопределения будут заменяться всюду, где бы они не встретились, даже внутри строки. Обратите внимание, что макроопределение PR использует это свойство препроцессора. Для более подробного описания макроопределений смотрите главу, посвященную препроцессору.