Директивы компилятора управляют режимом компиляции программы. Они представляют собой комментарии со специальным синтаксисом и могут быть поставлены в программе в любом месте, где разрешается комментарий.
Синтаксис директивы компилятора:
{$ <имя> <знак или параметр>}
Имеются три типа директив:
1. Ключевые директивы, которые включают или выключают конкретные режимы компиляции с помощью указания знаков "+" или "-" после имени директивы.
2. Директивы с параметрами, в которых после имени директивы записываются определенные параметры.
3. Директивы условной компиляции, управляющие порядком компиляции частей исходного текста программы.
Директивы могут быть глобальными или локальными. Глобальные директивы влияют на всю компиляцию, а локальные - только на ту часть программы, которая начинается с данной директивы и заканчивается следующим ее появлением.
Глобальные директивы должны указываться перед разделами описаний программы или модуля, в частном случае перед словами Program и Unit.
Несколько директив могут быть сгруппированы в одном комментарии с разделением их запятыми. Например,
{$B+, R+, S-}
В данном разделе будут рассмотрены наиболее часто используемые директивы.
1. Выбор типа вызова: {$F+} или {$F-} .
По умолчанию принято {$F-}. Тип директивы - локальный.
Как известно, адрес процедуры или функции может быть полным, т.е. состоящим из адреса сегмента и смещения, и коротким, состоящим только из смещения. В первом случае мы имеем дальний тип вызова (Far), во втором - ближний (Near).
Для процедур и функций, имена которых указаны в интерфейсной секции модуля, всегда генерируется дальний тип вызова, для локальных процедур и функций по умолчанию генерируется ближний тип.
Если задана директива F+, то для всех процедур и функций, кроме внутренних, генерируется дальний тип. Внутренние процедуры и функции всегда имеют короткий адрес вне зависимости от директивы F.
Установление директивы F+ требуется при использовании оверлеев, а также программ с процедурными переменными.
2. Контроль ввода-вывода: {$I+} или {$I-} .
По умолчанию принято {$I+}. Тип директивы - локальный.
Директива задает или отменяет автоматическое генерирование машинных команд, проверяющих результат выполнения операции ввода-вывода. Если процедура ввода-вывода возвращает ненулевой результат ее выполнения при включенной директиве I+, то программа завершает работу с выводом сообщения об ошибке ввода-вывода. В состоянии I- прерывания программы не происходит, а результат выполнения операции ввода-вывода можно проверить с помощью функции IOResult.
При обращении к функции IOResult ее выходное значение обнуляется.
Пример 1. Проверка наличия файла.
Procedure ExisFile(Var F:text; S:string);
Begin
{$I-} Reset(F); {$I+}
If IOResult<>0 then
Begin
Writeln('Файл ',S,' отсутствует'); Halt
End;
End{ ExisFile };
......................................
Begin
Assign(FileInput,'Input.dat');
ExisFile(FileInput,'Input.dat');
В этом случае можно сообщить, какой именно файл отсутствует в заданном каталоге.
Примечание. Если в вышеприведенной программе записать
{$I-} Reset(F); {$I+}
k:=IOResult;
If IOResult<>0 then... ,
то в этом случае некорректность операции ввода не будет обнаружена.
Пример 2. Проверка готовности принтера.
Procedure PrinterReady(Var Key:byte);
Var Cond : boolean;
Begin
Repeat
Cond:=true; Key:=0;
{$I-} Writeln(Lst); {$I+}
If IOResult<>0 then
Begin
Cond:=false;
Writeln('Включите принтер и проверьте ',
'его готовность,');
Writeln('после чего нажмите клавишу Enter.');
Writeln('Отмена печати - Esc');
Repeat
Key:=ord(ReadKey);
IfKey=27 then Exit;
Until Key=13;
End;
UntilCond;
End{ PrinterReady };
Процедура PrinterReady работает до тех пор, пока не будет устранена неготовность принтера или не будет отменена печать результатов. В последнем случае в вызывающей программе должно анализироваться значение выходной переменной Key.
Пример 3. Проверка ввода числового ответа.
Function GetNumberInt(S:string; MinNumber,
MaxNumber:longint):longint;
Var Number : longint;
k : integer;
Cond : boolean;
Begin
Writeln(S);
Repeat
Repeat
{$I-} Read(Number); {$I+}
k:=IOResult;
Ifk<>0 then
Begin
Writeln(#7'Неправильный формат числа');
Writeln('Повторите ввод');
End
Until k=0;
Cond:=(Number<=MaxNumber) and (Number>=MinNumber);
If not Cond then
Begin
Writeln(#7'Значение указано неверно:');
Writeln('Допустимый диапазон ',MinNumber,'..',
MaxNumber);
Writeln('Повторите ввод');
End;
Until Cond;
GetNumberInt:=Number;
End{ GetNumberInt };
Функция GetNumberInt производит проверку формата вводимого числа и диапазона его представления. При обнаружении ошибки пользователю предлагается повторить ввод.
3. Проверка границ: {$R+} или {$R-} .
По умолчанию принято {$R-}. Тип директивы - локальный.
Директива приводит в действие или отменяет генерирование машинных команд для проверки границ. При значении R+ все массивы и строки проверяются на условие принадлежности индекса допустимому диапазону его изменения. Проверке подвергаются также операторы присваивания значения ординальным переменным. При выходе индекса за пределы объявленных границ или при попытке присваивания ординальным переменным внедиапазонного значения программа прерывается и генерируется сообщение об ошибке. При включении директивы R+ компилятор добавляет в объектный код программы значительное количество машинных команд, вследствие чего объем программы увеличивается, а ее работа замедляется. Поэтому рекомендуется при отладке программы всегда использовать директиву R+, а после окончания отладки устанавливать значение R-.
Пример 4.
{$R+}
Type Ar = array[1..100] of real;
string40 = string[40];
Vark : byte;
m : integer;
n : 1..1000;
R : real;
ch : char;
A : Ar;
S : string40;
Begin
1) k := 400; 5) m := 400; k := m;
2) n := 2000; 6) m := 2000; n := m;
3) ch := S[50]; 7) k := 50; ch := S[k];
4) R := A[200]; 8) k := 200; R := A[k];
В этом примере в период компиляции будет зафиксировано нарушение границ для первых четырех операторов. При этом будет выдано сообщение "Error 76: Constant out of range". Для остальных операторов нарушение границ будет зафиксировано в период выполнения программы. При этом будет выдано сообщение "Error 201: Range check error".
4. Проверка переполнения стека: {$S+} или {$S-} .
По умолчанию принято {$S+}. Тип директивы - локальный.
Директива генерирует или отменяет код проверки переполнения стека. Во включенном состоянии этой директивы перед вызовом каждой процедуры и функции проверяется, достаточно ли места в сегменте стека для размещения ее локальных переменных. Если этого места недостаточно, программа прерывается и генерируется сообщение об ошибке.
5. Размеры выделяемой памяти: {$M Стек,Мин_об,Макс_об} .
Тип директивы - глобальный.
Директива определяет параметры распределения памяти программы. Параметр "Стек" указывает размер сегмента стека и может принимать значения в диапазоне 1024 .. 65520. Последние два параметра указывают минимальный и максимальный объем динамически распределяемой области памяти. Параметр "Мин_об" может быть задан в диапазоне 0 .. ..655360, параметр "Макс_об" - в диапазоне Мин_об .. 655360.