В интегрированную среду Visual C++, как обязательный компонент, входит препроцессор. Назначение препроцессора – анализ и обработка исходного текста программы до ее компиляции. Используя возможности прекомпиляции, можно создавать программы, компилируемые по-разному, в зависимости от текущих потребностей (например, строя или не строя отладочную информацию
Управление работой препроцессора осуществляется при помощи директив, включаемых в исходный код программы. В результате выполнения всех директив препроцессора, образуется новый вариант исходного кода программы, который затем компилируется. Итак, на входе препроцессора – текст с препроцессорными директивами, на выходе препроцессора – текст без препроцессорных директив.
Поясним, что понимается под препроцессорными лексемами или лексемами препроцессора (preprocessing token). К ним относятся символьные константы, имена включаемых файлов, идентификаторы, знаки операций, препроцессорные числа, знаки препинания, строковые константы (строки) и любые символы, отличные от пробела.
Директива #include
Эта директива предназначена для включения в исходный текст программы исходного кода из указанных файлов, например, заголовочных файлов. В коде программы строка, содержащая директиву, заменяется содержимым файла (одна строка – 8 страниц).
Допустимо вложение директив, т.е. в файле, на который указывает директива #include могут также использоваться директивы #include на другие файлы. Однако глубина такого вложения ограничена. Обычно допускается до 10 уровней вложения.
Существенный момент в использовании директивы #include состоит в способе задания имени файла:
#include <stdio.h>
#include “myhead.h”
если имя файла заключено в кавычки – файл будет искаться в том же каталоге, в котором находится файл программы, а если в угловые скобки – то сначала поиск осуществляется в специальном стандартном каталоге, определяемом при установке на компьютере системы программирования.
Директива #define.
Эта директива предназначена для решения двух задач:
1. сокращения длины кода
2. реализации макроопределений функций.
Первая задача решается следующим образом. Управляющая строка имеет вид
#define <идентификатор> <последовательность лексем>
заставляет препроцессор заменять идентификатор на последовательность лексем. Пробелы в начале и конце последовательности выбрасываются.
Вторая задача - реализация макроопределений функций, обеспечивается следующей конструкцией:
#define <имя макроса>(<параметры>) <выражение>
Например, определение
#define АВС(а,в) ((а)>(в) ? (а)-(в) : (в)-(а))
задает макрос, возвращающий абсолютное значение разности его аргументов. В отличие от функции, делающей то же самое, аргументы и возвращаемое значение здесь могут иметь любой арифметический тип, и даже быть указателями (так как здесь не задаются типы аргументов).
Управляющая строка вида #undefпредписывает препроцоссору забыть определение, данное идентификатору.
Другие директивы препроцессора: #if, #ifdef, #ifndef, #else, #endif
Командные строки препроцессора используются для условной компиляции различных частей исходного текста в зависимости от внешних условий.
#if <константное выражение>
Пример
#if ABC+3
Истина, если константное выражение ABC+3 не равно нулю.
#ifdef <идентификатор>
Пример
#ifdef ABC
Истина, если идентификатор ABC определен ранее командой # define.
#ifndef <идентификатор>
Пример
#ifndef ABC
Истина, если идентификатор ABC не определен в настоящий момент.
#else
…
#endif
Если предшествующие проверки: #if, #ifdef, #ifndef дают значение Истина, то строки от #else до #endif игнорируются при компиляции.
Если эти проверки дают значение Ложь, то строки от проверки до #else игнорируются. Команда #endif обозначает конец условной компиляции.