Пример:
#define ABC 100Заменяет каждое вхождение идентификатора ABC в тексте программы на 100:
#undef идентификаторПример:
#undef ABCОтменяет предыдущее определение для идентификатора ABC.
Пример:
/* Простые примеры директивы препроцессора */#define TWO 2 /* можно использовать комментарии*/#define MSG "Текст 1.\Продолжение текста 1"/* обратная косая черта продолжает определение на следующую строку */#define FOUR TWO*TWO#define PX printf("X равен %d.\n", x)#define FMT "X равен %d.\n"int main(){ int x = TWO; PX; x = FOUR; printf(FMT,x); printf("%s\n",MSG); printf("TWO:MSG\n"); return TWO;}В результате выполнения нашего примера будем иметь:
X равен 2X равен 4Текст 1. Продолжение текста 1TWO: MSGРазберем, что произошло. Оператор
int x = TWO;превращается в
int x = 2;Затем оператор
PX;превращается в
printf("X равно %d.\n",x);поскольку сделана полная замена. Теперь мы видим, что макроопределение может представлять любую строку, даже целое выражение на языке Си. Заметим, что это константная строка. PX напечатает только переменную, названную x.
В следующей строке выполняется следующее:
x = FOUR;превращается
x = TWO*TWO;превращается в
x = 2*2;и на этом все заканчивается. Фактическое умножение имеет место не во время работы препроцессора и не при компиляции, а всегда без исключения при работе программы (Уточнение: это зависит от конкретного компилятора). Препроцессор не выполняет вычислений. Он только очень точно делает предложенные подстановки. Заметим, что макроопределение может включать другие определения. Некоторые компиляторы не поддерживают это свойство вложения. В следующей строке
printf(FMT,x);превращается в
printf("X равно %d.\n",x)когда FMT заменяется соответствующей строкой. Этот подход может оказаться очень удобным, если есть длинная строка, которую мы используем несколько раз. В следующей строке программы MSG заменяется соответствующей строкой. Кавычки делают замещающую строку константой символьной строки. Поскольку программа получает ее содержимое, эта строка будет запоминаться в массиве, заканчивающемся нуль-символом. Так,
#define HAL 'X' определяет символьную константу, а #define HAR "X" определяет строковую строку X\0Обычно препроцессор, встречая одно из макроопределений в программе, очень точно заменяет их эквивалентной строкой замещения. Если эта строка также содержит макроопределения, они тоже замещаются. Единственным исключением при замене является макроопределение, находящееся внутри двойных кавычек. Поэтому
printf("TWO: MSG");печатает буквально TWO: MSG вместо печати следующего текста:
2: "Текст 1.Продолжение текста 1"Если нам нужно напечатать этот текст, можно использовать оператор
printf("%d: %s\n",TWO,MSG);потому что здесь макроопределения находятся вне кавычек.
Когда следует использовать символические константы? Вероятно, мы должны применять их для большинства чисел. Если число является константой, используемой в вычислениях, то символическое имя делает яснее ее смысл. Если число - размер массива, то символическое имя упрощает изменение вашей программы при работе с большим массивом. Если число является системным кодом, скажем для символа EOF, то символическое представление делает программу более переносимой. Изменяется только определение EOF. Мнемоническое значение, легкость изменения, переносимость: все это делает символические константы заслуживающими внимания!