Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка часть2.doc
Скачиваний:
22
Добавлен:
11.05.2015
Размер:
1.62 Mб
Скачать

12. Вспомогательные директивы.

В отличие от директив #include, #define и всего набора команд условной компиляции (#if...) рассматриваемые в данном параграфе директивы не так часто используются в практике программирования.

Препроцессорные обозначения строк. Для нумерации строк можно использовать директиву

#line константа

которая указывает компилятору, что следующая ниже строка текста имеет номер, определяемый целой десятичной константой. Директива может одновременно изменять не только номер строки, но и имя файла:

#line константа “имя файла”

Директиву #line можно «встретить» сравнительно редко, за исключением случая, когда текст программы на языке Си генерирует какой-то другой препроцессор.

Смысл директивы #line становится очевидным, если рассмотреть текст, который препроцессор формирует и передает на компиляцию. После препроцессорной обработки каждая строка имеет следующий вид:

имя_файла номер_строки текст_на _языке _Си

Например, пусть препроцессор получает для обработки файл “kkk.c” c таким текстом:

Пример 10.20

#define N 3 /* Определение константы */

void main() {

#line 23 “file.c”

double z[3*N]; }

После препроцессора в файле с именем “ kkk.i” будет получен набор строк:

kkk.c 1:

kkk.c 2: void main()

kkk.c: 3 {

kkk.c 4:

file.c 23: double z[3*3]

file.c 24 }

В результирующем тексте отсутствуют препроцессорные директивы и комментарии. Соответствующие строки пусты, но включены в результирующий текст. Для них выделены порядковые номера (1 и 4). Следующая строка за директивой #line обозначена в соответствии со значением константы (23) и указанным именем файла “file.c”.

13. Реакция на ошибки.

Обработка директивы

#error последовательность_лексем

приводит к выдаче диагностического сообщения в виде, определенном последовательностью лексем. Естественно применение директивы #error совместно с условными препроцессорными командами. Например, определив некоторую препроцессорную переменную NAME

#define NAME 5

в дальнейшем можно проверить ее значение и выдать сообщение, если у NAME окажется другое значение:

#if (NAME !=5)

#error NAME должно быть равно 5 !

Сообщение будет выглядеть так:

Error <имя_файла> <номвр_отроки>:

Error directive: NAME должно быть равно 5 !

В интегрированной среде сообщение будет выдано на этапе компиляции в таком виде:

Fatal <имя_файла> <номер_строки>:

Error directive: NAME должно быть равно 5!

В случае выявления такой аварийной ситуации дальнейшая препроцессорная обработка исходного текста прекращается, и только та часть текста, которая предшествует условию #if..., попадает в выходной файл препроцессора.

14. Пустая директива.

Существует директива, использование которой не вызывает никаких действий. Она имеет вид: #

Прагмы. Директива #pragmaпоследовательность лексем определяет действия, зависящие от конкретной реализации компилятора. Например, в некоторые компиляторы входит вариант этой директивы для извещения компилятора о наличии в тексте программы команд на языке ассемблера.

Возможности команды #pragma могут быть весьма разнообразными и важными. Стандарта для них не существует. Если конкретный препроцессор встречает прагму, которая ему неизвестна, он ее просто игнорирует, как пустую директиву. В некоторых реализациях включена прагма

#pragma pack(n) где n может быть 1, 2 или 4.

Эта прагма позволяет влиять на упаковку смежных элементов в структурах и объединениях.

Соглашение может быть таким:

pack(l) – выравнивание элементов по границам байтов;

раск(2) – выравнивание элементов по границам слов;

раск(4) – выравнивание элементов по границам двойных слов.

В некоторые компиляторы включены прагмы, позволяющие изменять способ передачи параметров функциям, порядок помещения параметров в стек и т.д.