Эта строка создает символическую константу AFXCE_IDR_SCRATCH_SHMENU со значением 28700. Теперь компилятор, обнаружив в тексте программы имя AFXCE_ IDR_SCRATCH_SHMENU, будет вместо него подставлять значение 28700. 4. Открыть в окне FileView файл aygshell.h. В этом файле нужно найти следующую строку кода:
#define CEM_UPCASEALLWORDS (WM_USER + 1)
Данное объявление говорит о том, что препроцессор, встретив вызов макрофункции CEM_UPCASEALLWORDS, вместо имени подставит выражение (WM_USER + 1). Макрофункция, как и любая другая функция, может принимать параметры. К примеру, объявление #define MF(a, b, c) (a*b*c/(a+b+c)) далее в тексте может быть использовано как MF(x, y, z). Вместо имени фунции с заданными аргументами препроцессор вставит тело функции, то есть (x*y*z/(x+y+z)). Файл newres.h начинается со строк:
#ifndef __NEWRES_H__ #define __NEWRES_H__
а завершается строкой:
#endif //__NEWRES_H__
Эти строки показывают еще одно применение директивы #define. Выражение #define __NEWRES_H__ при обработке препроцессором приведет к замене имени __NEWRES_H__ простым пробелом. На самом деле это выражение служит маркером для выполнения условной компиляции или условного включения. Таким образом, директива #define позволяет определить имя, которое нигде не появится в конечном тексте программы ни в виде символа, ни в виде значения, но будет служить условием выбора для самого препроцессора.
Эти строки дают возможность перейти к директивам условной компиляции (условного расширения). К этим директивам относятся #if, #ifdef, #ifndef, #endif, #else и #elif.
Директива условной компиляции #if позволяет управлять процессом компиляции проекта. Если выражение const_exp, стоящее после директивы #if в конструкции #if const_exp, имеет ненулевое значение, то текст, следующий за директивой #if до соответстующей ей директивы #endif, будет включен в текст, подаваемый на вход компилятора (а значит, и скомпилирован). В противном случае этот текст не попадет на вход компилятора и не войдет в программу.
Если имя ident, стоящее после директивы #ifdef в конструкции #if ident, определено в тексте программы, то текст, следующий за директивой #ifdef до соответстующей ей директивы #endif, будет включен в текст, подаваемый на вход компилятора.
Если имя ident, стоящее после директивы #ifndef в конструкции #ifndef ident, не определено в тексте программы, то текст, следующий за директивой #ifndef до соответствующей ей директивы #endif, будет включен в текст, подаваемый на вход компилятора.
В целом конструкция условной компиляции может выглядеть так, как показано в листинге 4.30.
Листинг 4.30#if cnst_ex1//Если выражение const_exp1 имеет значение true,
[text1]//тогда расширяется text1
[#elif cnst_ex2//иначе если cnst_ex2 имеет значение true,
text2]//тогда расширяется text2
[#elif cnst_ex3//иначе если cnst_ex3 имеет значение true,
text3]//тогда расширяется text3 … и так далее.
…
[#elif cnst_exN//если не был расширен ни один из предыдущих блоков,
textN]//расширяем текст textN
#endif//и завершаем блок условной компиляцииТеперь нужно проанализировать реальный код, который приведен в листинге 4.31. Листинг 4.31
/* Если имя __NEWRES_H__ не определено, */
#ifndef __NEWRES_H__
/* Определяем это имя и расширяем текст модуля */
#define __NEWRES_H__
[текст модуля]
#endif //__NEWRES_H__