Отправляет email-рассылки с помощью сервиса Sendsay

Всё о работе в Интернет

  Все выпуски  

Занятие 20.


Сегодня мы с вами, уважаемые подписчики, несколько отвлечёмся от построения алгоритмов решения задач и продолжим изучение материала, касающегося оформления программ на Паскале.

Радикальным средством обеспечения независимости создаваемых программ от настроек ИСП является использование директив компиляции.

ДИРЕКТИВЫ КОМПИЛЯЦИИ

1. Общие положения.

Нередки случаи, когда Паскаль-программа, отлаженная на одном компьютере, неудовлетворительно ведёт себя на другом. Большей частью это объясняется неодинаковыми настройками ИСП на этих компьютерах. Но это совсем не значит, что каждый раз на другом компьютере нужно заниматься перенастройкой ИСП. Гораздо проще и эффективнее оформить Паскаль-программу так, чтобы она стала независимой от конкретной настройки ИСП. Это достигается размещением в Паскаль-программе предваряющего набора директив компиляции. Такой набор в виде {$B+,D+,E+,I+,L+,N+,Q+,R+,X-} мы уже использовали в наших программах. Его смысл я обещал разъяснить позже. Этот момент наступил.

Заранее вынужден извиниться за возможное использование непонятных терминов и неопределённых понятий. Всему своё время, уважаемые подписчики!

Директивы компиляции используются для придания определённых свойств и особенностей исполняемой программе. Как правило, их размещают непосредственно перед текстом программы. В этом случае полный набор директив компиляции может быть получен автоматически посредством нажатия клавиш <Ctrl + O & O>. Далее он может быть отредактирован и приведён к нужному виду.

Директивы компиляции имеют вид комментария, обрамлённого фигурными скобками “{}”. Непосредственно за открывающей скобкой должен следовать символ “$”. Такой комментарий воспринимается компилятором как указание обеспечить соответствующие свойства компилируемой программы.

Большинство директив состоят из двух знаков. Первый знак – буква латинского алфавита, которая имеет определённый смысл. Вторым знаком такой директивы является “+” или “”, обозначающий действие или отмену действия данной директивы.

2. Вычисление логических выражений.

Во многих случаях результат вычисления логического выражения оказывается предопределённым, даже если вычисления не доведены до конца. Например, при A=1 вычисление логического выражения (A>0) Or (B=5) можно прекратить сразу после вычисления первого отношения (A>0). Поскольку оно истинно, и выполняться должна логическая операция Or, то результат будет истинным, независимо от значения второго отношения (B=5). Сходный пример может быть указан и для логической операции And. Вычисление выражения (A<0) And (B=5) также может быть прекращено на первом отношении. Поскольку оно ложно, то ложным будет и результат в целом. Очевидно, что учитывать возможность появления предопределённого результата полезно, поскольку при этом уменьшается количество вычислений.

Таким образом, принципиально возможны две схемы вычисления логических выражений. При вычислении логического выражения по полной схеме процесс осуществляется формально, то есть выражение вычисляется полностью от начала до конца и возможность появления предопределённого результата не учитывается. И наоборот, при вычислении логического выражения по сокращённой схеме, так же как и в вышеприведённых примерах, учитывается возможность появления предопределённого результата. Это значит, что в определённый момент процесс вычислений может быть прекращён, если в его продолжении нет фактической необходимости.

Установка сокращённой схемы вычисления логических выражений достигается с помощью указания в начале программы директивы компиляции {$B–}. При указании директивы компиляции {$B+} для данной программы устанавливается полная схема вычисления логических выражений.

3. Создание отладочной информации.

В процессе создания программы целесообразно пользоваться всеми средствами отладки программы, которые доступны нам в рамках ИСП (об этом мы будем говорить позже). Чтобы эти возможности могли быть реализованы, в процессе компиляции должна генерироваться отладочная информация.

Отладочная информация создаётся, если установлена директива компиляции {$D+}. Если, кроме того, установить директиву компиляции {$L+}, то в процессе отладки будут доступными не только переменные самой программы (глобальные), но и переменные, описанные в подпрограммах (локальные).

4. Настройка компилятора на вещественные типы.

Чтобы иметь возможность использовать при программировании любые вещественные типы, следует правильно настроить процесс компиляции программы. При этом необходимо помнить, что числа типа Real могут беспрепятственно использоваться на персональных компьютерах любых типов. Работа со всеми остальными вещественными типами может быть реализована по одной из двух возможных схем:

-       аппаратно, с помощью специального математического сопроцессора;

-       программно, посредством эмуляции (воспроизведения) работы математического сопроцессора.

Настройку процесса компиляции программы на использование вещественных типов определяют директива компиляции {$N±} – использование установленного сопроцессора или его программная эмуляция, а также директива {$E±} – использование эмуляции. Наиболее целесообразно использовать сочетание директив {$N+,E+}. Это значит, что компилятор ориентируется на выполнение операций с вещественными числами или с помощью математического сопроцессора (если он установлен), или с помощью подпрограмм эмуляции (если сопроцессор отсутствует). При этом наличие сопроцессора определяется автоматически. Он будет использоваться в случае его обнаружения, или же его работа будет эмулироваться в противном случае.

5. Контроль операций ввода-вывода.

Программист имеет возможность подключить к своей программе средства, которые будут автоматически контролировать правильность выполнения операций ввода-вывода данных. Для этого он должен использовать директиву компиляции {$I+}.

При использовании директивы {$I–}, противоположной по смыслу, программист должен будет сам организовать в своей программе анализ успешности выполнения операций ввода-вывода. Такой анализ может быть осуществлён с помощью стандартной целочисленной функции IOResult: Integer. Её значением является код ошибки последней из выполненных операций ввода-вывода. Например, код ошибки 106 означает неправильный числовой формат (Invalid numeric format). Нулевое же значение кода свидетельствует об отсутствии ошибок.

Если автоматический контроль отключён, то в программе к функции IOResult следует обратиться обязательно. В противном случае, если произойдёт ошибка ввода-вывода, то все последующие операции ввода-вывода программы будут просто проигнорированы. Отметим также, что результативным может быть лишь однократное обращение к этой функции, поскольку её значение при этом сбрасывается.

6. Контроль ситуаций переполнения и выхода за границы.

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

При выполнении операций присваивания могут возникать ситуации выхода значений переменных и индексов за допустимые границы, предусмотренные их типами.

При использовании директив компиляции {$Q+} и {$R+} над указанными ошибочными ситуациями устанавливается контроль, выполняемый операционной системой во время работы программы. При этом переполнение и выход за границы приводят к завершению выполнения программы и выдаче соответствующего сообщения об ошибке.

Следует помнить, что при использовании директивы {$Q–} для целочисленных операций во многих случаях есть риск получить неправильный результат, не подозревая об этом. Например:

-       при A: Integer=200 для выражения A*190 получаем значение –27536;

-       при x: Byte=1 оператор WriteLn(2147483647 + x) выводит число –2147483648 и т.п.

7. Расширенный синтаксис.

В ИСП предусмотрены некоторые элементы, так называемого, расширенного синтаксиса. К их числу относится возможность обращения к функциям не только в составе выражений, но и в виде отдельного оператора, то есть как к процедурам. Для этого следует использовать директиву компиляции {$X+}.

Разумеется, если записать обращение к функции в виде отдельного оператора, то само значение функции будет при этом теряться. Поэтому делать это имеет смысл в тех случаях, когда среди параметров функции есть ещё дополнительные параметры-переменные, которые могут передавать значения других её результатов.

Указанная возможность не относится к стандартным функциям.

Кроме того, установка расширенного синтаксиса необходима при обработке в программе ASCIIZ-строк.

8. Работа со стеком.

На использовании стека построен весь механизм вызова подпрограмм. Особенно активная работа со стеком ведётся при рекурсивных обращениях.

Размер стека для реального режима работы процессора (Real Target) можно регулировать непосредственно в программе с помощью директивы компиляции {$M 65520,0,655360}, в которой первое число указывает размер стека в пределах от 1024 до 65520 байт. Например, минимальный размер стека в 1024 байт устанавливается директивой {$M 1024,0,655360}.

Ограниченность размеров стека приводит к необходимости контроля его заполняемости в процессе работы программы во избежание его переполнения.

Упомянутый контроль может быть установлен с помощью директивы компиляции {$S+}, в результате действия которой при переполнении стека работа программы прерывается и появляется сообщение об ошибке “Error 202: Stack overflow error”.

Если снять контроль переполнения стека, установив директиву компиляции {$S–}, то, независимо от установленного размера стека, ничего плохого не происходит, пока заполненная его часть не превышает 65520 байт. При превышении указанного граничного значения процессор персонального компьютера обнаруживает недопустимую инструкцию, после чего программа автоматически снимается с выполнения.

9. Дальняя модель вызова подпрограмм.

Архитектурой персонального компьютера предусмотрено разбиение его оперативной памяти на сегменты, размером 64 Кбайт каждый. При этом могут использоваться как короткие адреса (в пределах сегмента), так и полные адреса (с указанием номера сегмента). Соответственно могут использоваться и две модели обращения к подпрограммам: ближняя (Near) и дальняя (Far). В случае ближней модели адресация выполняется в пределах сегмента памяти. Дальняя модель обеспечивает межсегментные связи.

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

Установка дальней модели для тех процедур и функций, которым она требуется, осуществляется с помощью стандартной директивы Far. Эти директивы должны указываться непосредственно после заголовков процедур и функций. Дальняя модель вызова подпрограмм может быть установлена также для всей программы в целом. Для этого перед началом программы должна указываться директива компиляции {$F+}. В этом случае указание директив Far не требуется.

Рассмотренный механизм не распространяется на стандартные процедуры и функции Паскаля.

Компиляция с расчётом на дальнюю модель вызова подпрограмм необходима также при построении программ с оверлейной структурой, при вызове одних программ из других с помощью оператора Exec и пр.

10. Контроль типов строк.

С помощью директивы компиляции {$V+} для данной программы может быть установлен автоматический контроль типов строк, передаваемых в качестве фактических параметров подпрограммы.

Этот контроль состоит в том, что в общем случае между типами фактических и формальных параметров-переменных должно быть полное совпадение. А исключения из этого правила таковы:

-       имена типов фактических и формальных параметров-переменных могут быть различными, но только в том случае, если это различные имена для одного и того же типа;

-       если тип формального параметра-переменной стандартный строковый, то совпадение типов для фактических параметров не обязательно.

Типы формальных и фактических параметров-значений считаются совместимыми в любых случаях.

Однако, с помощью директивы компиляции {$V–} автоматический контроль типов строк, передаваемых в качестве фактических параметров подпрограмм, можно отменить, поскольку на практике серьёзного значения этот контроль не имеет. В этом случае формальные и фактические параметры-переменные стандартных и нестандартных типов считаются совместимыми всегда.

Уважаемые подписчики! Все те непонятные термины и неопределённые понятия, которые нам встретились в материале о директивах компиляции, мы обязательно рассмотрим позже, когда это будет уместно с точки зрения логики изложения.

Уважаемые подписчики! При необходимости задать вопрос, проконсультироваться, уточнить или обсудить что-либо обращайтесь через Гостевую книгу моего персонального сайта http://a-morgun.narod.ru

С уважением, Александр.

 


В избранное