1) Препроцессорные обозначения строк
#line константа | Указывает компилятору, что следующая строка программы имеет номер, определяемый целой десятичной константой. |
Директива может одновременно изменять и имя файла:
#line константа “имя_файла“
После препроцессорной обработки каждая строка программы имеет вид:
Имя_файла номер_строки: текст_строки
2) Реакция на ошибки
#error последовательность_лексем | Выдаёт диагностическое сообщение в виде последовательности лексем |
Например:
#define N 1
...
#if (N!= 10)
#error N not equal 10!
#endif
...
Сообщение об ошибке в окне Output будет выглядеть так:
имя_файла(номер_строки): fatal error C1189:
#error: N not equal 10!
В случае обнаружения ошибки препроцессорная обработка прекращается и в выходной файл препроцессора попадает только та часть текста, которая предшествовала #if.
3) Пустая директива
# | Не вызывает никаких действий. |
4) Прагмы
#pragma последовательность_лексем | Определяет действия, зависящие от конкретной реализации компилятора. |
Для каждого компилятора существует свой набор прагм, управляющих процессом компиляции. Если препро-цессор встречает прагму, которая ему неизвестна, он её игнорирует как пустую директиву. Например, в Microsoft Visual Studio С++
#pragma pack(n) | влияет на упаковку смежных элементов в структурах, объединениях и объектах |
классов (n = 1,2,4); осуществляетвыравнивание элементов в памяти по границам байтов (n = 1), машинных слов (n = 2), двойных слов (n = 4) и т.д.
#pragma once | помещается в первой строке заголовочного файла и обеспечивает защиту от его повторного включения при использовании директивы #include. |
5) Предопределенные макросы
Предопределенные макросы – заранее определённые макроимена – выдают информацию о версии программы и месте возникновения ошибки.
__LINE__ | – | десятичная константа – номер текущей строки обрабатываемого текста (начинается с 1); |
__FILE__ | – | строка символов – имя компилируемого файла (изменяется, когда препроцессор встречает директиву #include, и восстанавливается после включения файла); |
__DATE__ | – | строка символов в формате “месяц число год” – дата начала обработки исходного файла; |
__TIME__ | – | строка символов в формате “час:мин:сек” – время начала обработки исходного файла; |
__STDC__ | – | константа, = 1, если компилятор соответствует ANSI-стандарту; в противном случае не определено; |
__cplusplus | – | равно 1, если компилируется программа на языке С++; в противном случае не определено: #ifdef __cplusplus ... // Действия С++ #endif |
Макросы __FILE__, __DATE__ и __TIME__ могут использоваться в сообщениях, выдаваемых в начале программы, для указания используемой версии программы, например,
cout << "Файл " << __FILE__ << " от "
<< __DATE__ << endl;
В конкретных реализациях языка набор предопределённых имён шире.
Задание.
1. Создать программу на языке С++, в которой алгоритм сортировки одномерного массива оформить в виде макроопределения шаблона функции (см. листинг 11.5).
Алгоритм сортировки (см. Приложение 1) выбирается следующим образом (N – номер слушателя по журналу):
если N % 6 = 0 - сортировка выбором (по возрастанию),
если N % 6 = 1 - сортировка обменами (по возрастанию),
если N % 6 = 2 - сортировка вставками (по возрастанию),
если N % 6 = 3 - сортировка выбором (по убыванию),
если N % 6 = 4 - сортировка обменами (по убыванию),
если N % 6 = 5 - сортировка вставками (по убыванию).
Отсортировать:
а) Массив целых чисел (число элементов n = 50). Массив заполнить, используя генератор случайных чисел.
б) Массив вещественных чисел (n = 25). Массив заполнить считыванием из текстового файла.
2. Вывод значений массива на экран оформить в виде макроса (см. листинг 11.4).
3. Создать и проанализировать файл с результатами препроцессорной обработки текста программы (см. Приложение 2).