ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Часть 8 Введение ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Данное руководство посвящено используемому в Borland Pascal with Objects языку Паскаль. Оно * Дает формальное определение языка Borland Pascal. * Поясняет, как использовать и писать динамически компонуе- мые библиотеки. * Знакомит вас с библиотекой исполняющей системы. * Поясняет, как писать программы для защищенного режима DOS. * Освещает такие вопросы Borland Pascal, как использование памяти, форматы данных, соглашения по вызову, ввод и вывод и автоматическая оптимизация. * Описывает, как использовать Borland Pascal с языком ас- семблера. Примечания: Обзор всего набора документации по Borland Pascal вы можете найти во введении к "Руководству пользова- теля". Если вы - хотите узнать, как установить Borland Pascal в системе; - использовали Turbo Pascal или Turbo Pascal for Windows ра- нее и хотите узнать, что нового в этой версии; - не знакомы с интерактивной интегрированной средой разра- ботки программ (IDE) фирмы Borland; - хотите познакомиться с введением в объектно-ориентирован- ное программирование; - не имеете опыта программирование на Паскале в Windows; - хотите познакомиться с ObjectWindows; то прочитайте "Руководство пользователя". Чтобы найти справочные материалы по следующим темам: - библиотеки исполняющей системы; - директивы компилятора; - сообщения об ошибках; - работа с редактором; прочтите "Справочное руководство программиста". О чем рассказывается в данном руководстве ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Данное руководство разбито на четыре части: грамматика язы- ка, библиотеки, вопросы продвинутого программирования и использо- вание с Borland Pascal языка ассемблера. В Части I "Язык Borland Pascal" определяется язык Borland Pascal. Сначала вы познакомитесь с общей структурой программы Borland Pascal; затем о каждом элементе программы будет рассказа- но более подробно. Часть II "Библиотеки исполняющей системы" содержит информа- цию о стандартных модулях, образующих библиотеку исполняющей сис- темы, и о том, как их использовать. Здесь рассказывается также, как писать программы для защищенного режима DOS. В Части III "В среде Borland Pascal" дается техническая ин- формация для продвинутых пользователей. Здесь рассказывается: - об использовании памяти в Borland Pascal; - о том, как в Borland Pascal реализовано управление прог- раммой; - о деталях по вводу и выводу; - об оптимизации вашего кода. В Части IV "Использование Borland Pascal с языком ассембле- ра" поясняется, как использовать встроенный ассемблер и как ком- поновать ваши программы Паскаля с кодом Турбо Ассемблера. Часть I. Язык Borland Pascal ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Глава 1. Что такое программа Borland Pascal? ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Следующие несколько глав посвящены формальному определению языка Borland Pascal. В каждой главе обсуждается один из элемен- тов Borland Pascal. Совместно эти элементы образуют программу Borland Pascal. Однако, изучая части, трудно понять целое. В данной главе дается общий обзор программы Borland Pascal, опуская детали. Здесь приводится краткое описание каждого элемента программы, а затем показывается, как все это компонуется вместе. Подробности элементов языка освещаются главах 2 - 11. Программа Borland Pascal ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В своей простейшей форме программа Borland Pascal состоит из заголовка программы, который именует программу, и основного прог- раммного блока, выполняющего назначение программы. В основном программном блоке находится секция кода, заключенная между ключе- выми словами begin и end. Приведем простейшую программу, иллюст- рирующую эти принципы: program Privet; begin Writeln('Добро пожаловать в Borland Pascal'); end. Первая строка - это заголовок программы, который именует данную программу. Остальная часть программы - это исходный код, который начинается ключевым словом begin и заканчивается end. Хо- тя данная конкретная программа содержит только одну строку, их может быть много. В любой программе Borland Pascal все действия выполняются между begin и end. Процедуры и функции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Код между последними операторами begin и end программы уп- равляет логикой программы. В очень простой программе в этой сек- ции кода может содержаться все, что вам нужно. В более крупных и сложных программах размещение в этой секции всего программного кода может затруднить чтение и понимание программы. К тому же ее будет труднее разрабатывать. Процедуры и функции позволяют разделить логику программы на более мелкие и управляемые фрагменты и аналогичны подпрограммам в других языках. Как и в основном блоке программы, все действия в процедурах и функциях заключаются в begin и end. Каждый из этих сегментов кода выполняет конкретную задачу. ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і Процедура или функция і іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Заголовок процедуры или функции іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Блок процедуры или функциями іі іі begin іі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі ііі Логика ііі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі іі end; іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Рис. 1.1 Диаграмма процедуры или функции. Если вы обнаружите, что в вашей диаграмме одни и те же дейс- твия выполняются многократно, такую логику желательно выделить в процедуру или функцию. Вы можете один раз записать этот код в процедуре или функции, а затем многократно вызывать его в прог- рамме. Приведем пример функции. Следующая функция GetNumber получа- ет число от пользователя: function GetNumber: Real; var Responce: Real; begin Write('Введите число: '); Readln(Response); GetNumber := Response; end; Процедура или функция должна содержаться в программе перед секцией основного кода. В основном коде она может затем использо- ваться (вызываться). ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і Процедура или функция і іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Заголовок процедуры или функции іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Блок процедуры или функциями іі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі ііі Процедуры или функции (0 или более) ііі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі іі begin іі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі ііі Логика ііі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі іі end; іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Рис. 1.2 Простая программа на Паскале. В следующем примере дается набросок программы, в которой ис- пользуется функция GetNumber. Программист разделил логику прог- раммы на три задачи: 1. Получение числа от пользователя. 2. Выполнение с этим числом необходимых вычислений. 3. Печать отчета. Основная логика программы заключена в последнем блоке begin..end. Program Report; var A: Real; { другие описания } . . . function GetNumber: Real; var Responce: Real; begin Write('Введите число: '); Readln(Response); GetNumber := Response; end; procedure Calculate(X: Real); . . . procedure PrintReport; . . . begin A: = GetNumber; Calculate(A); PrintReport; end. Основная логика программы достаточно проста для понимания. Все детали убраны в тела процедур и функций. Использование проце- дур и функций позволяет вам рассматривать программу более удобным и модульным способом. Операторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Исходный код между begin и end содержит операторы, которые описывают выполняемые программой действия. Это называются опера- торной частью программы. Приведем примеры операторов: A := B + C; { присвоить значение } Calculate(Length, Height); { активизировать процедуру } if X < 2 then { оператор условия } Answer := X * Y; begin { составной оператор } X := 3; Y := 4; Z := 5; end; while not EOF(InFile) do { оператор цикла } begin ReadLn(InFile, Line); Process(Line); end; В простых операторах можно присваивать значение, активизиро- вать процедуру или функцию или передавать управление на другую часть кода. Структурные операторы могут быть составными и содер- жать несколько операторов, оператор цикла или оператор условия, управляющий логикой программы, а также операторы with, упрощающие доступ к данным в записи. Выражения ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор Паскаля состоит из выражений. Выражения оператора могут состоять из операндов и операций. Обычно в выражениях вы- полняется сравнение либо арифметические, логические или булевские операции. Выражения Паскаля могут состоять из более простых выражений. О комбинации операндов и операций вы можете прочитать в Главе 6. Они могут быть достаточно сложными. Приведем некоторые примеры выражений: X + Y Done <> Error I <= Length -X Лексемы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Лексемы - это наименьшие значащие элементы в программе Пас- каля. Они образуются операндами и операциями выражений. Лексемы - это специальные символы, зарезервированные слова, идентификаторы, метки и строковые константы. Приведем примеры лексем Паскаля: function { зарезервированное слово } ( { специальный символ } := { специальный символ } Calculate { идентификатор процедуры } 9 { число } Приведем пример, из которого вы можете видеть, что операторы состоят из выражений, которые в свою очередь состоят из лексем. ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і Операторы (1 или более) і іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Выражения (1 или более) іі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі ііі Лексемы (1 или более) ііі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Рис. 1.3 Диаграмма оператора. Типы, переменные, константы и типизированные константы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Переменная может содержать изменяемое значение. Каждая пере- менная должна иметь тип. Тип переменной определяет множество зна- чений, которые может иметь переменная. Например, в следующей программе описываются переменные X и Y, имеющие тип Integer. Таким образом, X и Y могут содержать только целые значения (числа). Если в вашей программе предприни- мается попытка присвоить этим переменным значения другого типа, Borland Pascal сообщает об ошибке. program Example; const A = 12; { константа A не изменяет значения } B: Integer = 23; { типизированная константа B получает начальное значение } var X, Y: Integer; { переменные X и Y имеют тип Integer } J: Real; { переменная J имеет тип Real } begin X := 7; { переменной X присваивается значение } Y := 7; { переменной Y присваивается значение } X := Y + Y; { значение переменной X изменяется } J := 0.075; { переменной J присваивается значение с плавающей точкой } end. В этой простой и не очень полезной программе X первоначально присваивается значение 7; двумя операторами ниже ей присваивается новое значение: Y + Y. Как можно видеть, значение переменной мо- жет изменяться. A - это константа. Программа назначает ей значение 12, и это значение изменяться не может - в ходе выполнения программы оно остается постоянным. B представляет собой типизированную константу. Ей присваива- ется значение при описании, но дается также тип Integer. Типизи- рованую константу можно рассматривать как переменную с начальным значением. Позднее программа может изменить первоначальное значе- ние B на какое-то другое значение. Если вы вернетесь обратно к приведенному в начале главы при- меру кода, то увидите, что функция GetNumber имеет раздел описа- ний, в котором описывается переменная. Процедуры и функции могут содержать разделы описаний также как программы и модули. Компоновка частей ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Теперь, когда вы познакомились с основными компонентами программы Borland Pascal, давайте посмотрим, как все это работает вместе. Приведем диаграмму программы Borland Pascal: ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і Программа на Паскале і іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Заголовок программы іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Необязательные операторы uses іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїі іі Основной блок программы іі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі ііі Описания ііі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі ііі Процедуры или функции (0 или более) ііі іііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїііі іііі Описания іііі іііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩііі ііі begin ііі ііі ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїііі ііі і Операторы (1 или более) іііі ііі АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩііі ііі end; ііі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі іі begin іі іі ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіі іі і Операторы (1 или более) ііі іі іЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїііі іі іі Выражения (1 или более) іііі іі ііЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДїіііі іі ііі Лексемы (1 или более) ііііі іі ііАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіііі іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩііі іі АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩіі іі end. іі іАДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩі АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Рис. 1.4 Расширенная диаграмма программы на Паскале. Программу на Паскале составляют заголовок программы, необя- зательный оператор uses (о нем будет рассказано позднее) и основ- ной блок программы. В основном блоке могут присутствовать более мелкие блоки процедур и функций. Хотя на диаграмме это не пока- зано, процедуры им функции могут быть вложенными в другие проце- дуры или функции. Другими словами, блоки могут содержать другие блоки. В сочетании с другими лексемами и пробелами лексемы могут образовывать выражения, формирующие оператор. Операторы, в свою очередь, в сочетании с разделом описаний образуют блоки основной программы или блок в процедуре или функции. Модули ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Программа Borland Pascal может использовать блоки кода в программных модулях. Модуль (unit) можно рассматривать как ми- ни-программу, которую может использовать ваша прикладная програм- ма. Как и программа, он имеет заголовок (который называется заго- ловком модуля) и основной блок, ограниченный begin и end. Основной блок любой программы Borland Pascal может включать в себя строку, позволяющую программе использовать один или более модулей. Например, если вы пишете программу DOS с именем Colors и хотите изменять цвета выводимого на экран текста, то ваша прог- рамма может использовать стандартный модуль Crt, являющийся частью библиотеки исполняющей системы Borland Pascal: program Colors; uses Crt; begin . . . end. Строка uses Crt сообщает Borland Pascal, что нужно включить модуль Crt в выполняемую программу. Кроме всего прочего, модуль Crt содержит весь необходимый код для изменения цвета в вашей программе. Путем простого включения uses Crt ваша программа может использовать весь код, содержащийся в модуле Crt. Поэтому опера- тор uses называют также оператором использования. Если бы вы по- местили весь код, необходимый для реализации функциональных воз- можностей Crt, в свою программу, это потребовало бы огромных уси- лий и отвлекло бы вас от основной цели программы. Библиотеки исполняющей системы Borland Pascal включают в се- бя несколько модулей, которые вы найдете весьма полезными. Напри- мер, благодаря использованию модулей Dos или WinDos, ваша прог- рамма может получить доступ к нескольким подпрограммам операцион- ной системы и подпрограммам работы с файлами. Вы можете также писать свои собственные модули. Применяйте их для разделения больших программ на логические связанные фраг- менты. Программный код, который вы помещаете в модуль, может ис- пользоваться любой программой. Вам нужно написать исходный код только один раз, а затем вы сможете много раз его использовать. Синтаксические диаграммы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД При изучении глав 2 - 11, где определяется язык Borland Pascal, вы встретите синтаксические диаграммы, например: ЪДДДї ЪДДДДДДДДДДДДДДї ЪДДДї константа-массив ДДД>і ( ГДДДД>ітипизированнаяГДДВД>і ) ГДД> АДДДЩ ^ і константа і і АДДДЩ і АДДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДґ , і<ДДДДДДДДЩ АДДДЩ Чтобы прочитать диаграмму, следуйте по стрелкам. Часто встречаются альтернативные пути: путь, начинающийся слева и за- канчивающийся стрелкой справа, является допустимым. Путь пересе- кает блоки, содержащие имена элементов, используемых для построе- ния этой части синтаксиса. Имена в прямоугольных рамках с текстом должны быть заменены действительными конструкциями. Некоторые рамки содержат зарезер- вированные слова, знаки операций и знаки пунктуации, то есть фак- тические термы, используемые в программе. Имена в блоках - это конструкции языка. Имена, написанные по-английски (например, procedure), представляю собой зарезервированные слова и операции Borland Pascal. Глава 2. Лексемы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Лексемы - это минимальные значимые единицы текста в програм- ме, написанной на Паскале. Они представлены такими категориями как специальные символы, идентификаторы, метки, числа и строковые константы. Программа, написанная на Паскале, состоит из лексем и разде- лителей, причем разделитель представляет собой пробел или коммен- тарий. Две соседние лексемы, если они представляют собой зарезер- вированное слово, идентификатор, метку или число, должны быть отделены друг от друга одним и несколькими разделителями. Примечание: Разделители не могут быть частью лексем, за исключением строковых констант. Специальные символы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Borland Pascal использует следующие подмножества набора сим- волов кода ASCII: * Буквы - буквы английского алфавита от A до Z и от a до z. * Цифры - арабские цифры от 0 до 9. * Шестнадцатиричные цифры - арабские цифры от 0 до 9, буквы от A до F и буквы от a до f. * Разделители - символ пробела (ASCII 32) и все управляющие символы кода ASCII (ASCII 0-31), включая символ конца строки или символ возврата (ASCII 13). буква і АДДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДї і і і і v v v v ЪДДДї ЪДДДї ЪДДДї ЪДДДї і A і ... і Z і і a і ... і z і АДВДЩ АДВДЩ АДВДЩ АДВДЩ і і і і АДДДДДДДДДДДДДДБДДДДДДДДДДДДДДБДДДДДДДДДДДДДДБДДДД> цифра і АДДДДДДВДДДДДДДДДДДї і і v v ЪДДДї ЪДДДї і 0 і ... і 9 і АДВДЩ АДВДЩ і і АДДДДДДДДДДДБДДДДДДД> шестнадцатиричная цифра і ЪДДДДДДДДДДДї АДДДДДДДД>і цифра іДДДДДДДДДДДДДДДДДДДДДДДДДї і АДДДДДДДДДДДЩ і і і АДДДВДДДДДДДДДВДДДДДДДДДВДДДДДДДДДї і і і і і і v v v v і ЪДДДї ЪДДДї ЪДДДї ЪДДДї і і A і .. і F і і a і ... і f і і АДВДЩ АДВДЩ АДВДЩ АДВДЩ і і і і і і АДДДДДДДДДБДДДДДДДДДБДДДДДДДДДБДДДДДДДДДБДДДДДДДДД> Специальные символы и зарезервированные слова представляют собой символы, имеющие одно или несколько фиксированных значений. Специальными символами являются следующие одиночные символы: + - * / = < > [ ] . , ( ) : ; ^ @ { } $ # Следующие пары символов также представляют собой специальные символы: <= >= := .. (* *) (. .) Кроме того, некоторые специальные символы являются знаками операций. Левая квадратная скобка ([) эквивалентна паре символов, состоящей из левой круглой скобки и точки ((.). Аналогично правая квадратная скобка (]) эквивалентна паре символов, состоящей из точки и правой круглой скобки (.)). Зарезервированные слова и стандартные директивы Borland Pascal ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Следующие слова являются зарезервированными в Borland Pascal: Зарезервированные слова Borland Pascal Таблица 1.1 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД and exports mod shr array file nil string asm for not then begin function object to case goto of type const if or unit consatructor implementation packed until destructor in procedure uses div inherited program var do inline record while downto interface repeat with else label set xor end library shl ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В настоящем руководстве зарезервированные слова записаны строчными буквами. Однако, для Borland Pascal безразличен регистр клавиатуры, поэтому вы можете использовать в своей программе бук- вы как нижнего, так и верхнего регистра. Далее приведены стандартные директивы Borland Pascal. В от- личие от зарезервированных слов пользователь может их переопреде- лить. Однако делать это не рекомендуется. Стандартные директивы Borland Pascal Таблица 1.2 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД absolute far name resident assembler forward near virtual export index private external interrupt public ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Идентификаторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Идентификаторы выступают в качестве имен констант, типов, переменных, процедур, модулей, программ и полей в записях. Идентификатор может иметь любую длину, однако только первые его 63 символа являются значимыми. Идентификатор должен начинать- ся с буквы и не может содержать пробелов. После первого символа идентификатора можно использовать буквы, цифры и символы подчер- кивания (значение ASCII $5F). Как и в зарезервированных словах, в идентификаторах можно использовать как строчные, так и прописные буквы (компилятор их не различает). Идентификатор должен начинаться с буквы и не должен содер- жать пробелов. После первого символа допускаются буквы, цифры и символ подчеркивания (ASCII $5F). Как и зарезервированные слова, идентификаторы безразличны к регистру клавиатуры. Когда имеется несколько мест с указанием одного и того же идентификатора, для задания нужного идентификатора необходимо уточнить этот идентификатор с помощью идентификатора модуля. Нап- ример, для уточнения идентификатора Ident с помощью идентификато- ра модуля UnitName следует записать UnitNamt.Ident. Такой комби- нированный идентификатор называется уточненным идентификатором. Примечание: Модули описываются в Главе 7 "Руководства пользователя" и в Главе 10 данного руководства. ЪДДДДДДДДДДДї Идентификатор ДДВДДД>і буква іДДДДДДДДДДДДДДДДДДДДДДДДДВД> і АДДДДДДДДДДДЩ ^ ^ і і ЪДДДДДДДДДДДДДї і і і АД>і символ ГДЩ і ЪДДДДДДДДДДДДДї і іподчеркиванияі ГДДДґ буква і<ДДґ АДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і ГДДДґ цифра і<ДДґ і АДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і АДДДґ символ і<ДДЩ іподчеркиванияі АДДДДДДДДДДДДДЩ ЪДДДї символ подчеркиванияДДДДД>і _ іДДДДД> АДДДЩ идентификатор программы ЪДДДДДДДДДДДДДї идентификатор модуля ДДДДД>іидентификаторіДДДД> идентификатор поля АДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДї уточненный ДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДґ идентификатор ГДД> идентификатор і ^ АДДДДДДДДДДДДДДДЩ і ЪДДДДДДДДДДДДДї ЪДДДї і АД>іидентификаторГД>і . ГДЩ і модуля і АДДДЩ АДДДДДДДДДДДДДЩ Приведем несколько примеров идентификаторов: Writeln Exit Real2String System.MemAvail Dos.Exec WinCrt.Windows Числа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Для чисел, представляющих собой константы целого и вещест- венного типа, используется обычная десятичная запись. Целая конс- танта в шестнадцатиричном формате имеет в качестве префикса знак доллара ($). Техническое обозначение (E или е с показателем сте- пени) в вещественных типах читается, как "на десять в степени". Например, 7E-2 означает 7х10^-2, а 12.25E+6 или 12.25E6 оба обозначают 12.25х10^+6. Синтаксические диаграммы для записи чисел приведены ниже. ЪДДДДДДДДДДДДДДДДДї последовательность ДДДДДДДД>ішестнадцатиричнаяГДДДДДДДВДД> шестнадцатиричных ^ і цифра і і цифр і АДДДДДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДї последовательность ДДДДДДДД>і цифра ГДДДДДДДВДДД> цифр ^ АДДДДДДДДДДДДДДДДДЩ і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДї целые без знака ДДДДВДДДД>іпоследовательностьГДДДДДДДДДДД> і і цифр і ^ і АДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДї ЪДДДДДДДДДДДДДДБДДДї АДДДД>і $ іДДДД>іпоследовательностьі АДДДЩ ішестнадцатиричных і і цифр і АДДДДДДДДДДДДДДДДДДЩ ЪДДДї знак ДВДДД>і + ГДДДДДДД> і АДДДЩ ^ і ЪДДДї і АДДД>і - ГДДДЩ АДДДЩ вещественное без знака і ЪДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДї АДД>іПоследова-ГДВД>і . ГД>іпоследова-ГДДВДДДДДДДДДДДДДДДДДД ітельность і і АДДДЩ ітельность і і ^ і цифр і і і цифр і і і АДДДДДДДДДДЩ і АДДДДДДДДДДЩ і і і v ЪДДДДДДДДДДї і АДДДДДДДДДДДДДДДДДДДДДДДДД>імасштабныйГДЩ і множительі АДДДДДДДДДДЩ масштабный множитель і ЪДДДї ЪДДДДДДДДДДДДДДДДДДї АДДДДДДДВД>і E ГДДДДДВДДДДДДДДДДДД>іпоследовательностьГДД> і АДДДЩ ^ і ^ і цифр і і ЪДДДї і і ЪДДДДї і АДДДДДДДДДДДДДДДДДДЩ АД>і е ГДЩ АД>ізнакГДДЩ АДДДЩ АДДДДЩ число без знака і ЪДДДДДДДДДДДДДДДї АДДДДДДДДДДДВД>іцелое без знакаГДДДДДДДД> і АДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДї і АД>івещественноеГДДДДДДДЩ ібез знака і АДДДДДДДДДДДДЩ число со знаком і ЪДДДДДДДДДДДДДДДї АДДДДДДДДВДДДДДДДДДДДДДДДД>ічисло без знакаГДДДД> і ^ АДДДДДДДДДДДДДДДЩ і ЪДДДДї і АД>ізнакГДДДДДЩ АДДДДЩ Числа с десятичными точками или показателями степени предс- тавляют собой константы вещественного типа. Остальные десятичные числа обозначают константы целого типа. Они должны принимать зна- чения в диапазоне от -2147483648 до 2147483647. Шестнадцатиричные числа обозначают константы целочисленного типа. Они должны находиться в диапазоне от $00000000 до $FFFFFFFF. Окончательный знак значения определяется шестнадцати- ричной записью. Метки ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Меткой является последовательность цифр в диапазоне от 0 до 9999. Начальные нули не являются значащими. Метки используются с операторами перехода goto. ЪДДДДДДДДДДДДДДДДДДДДДДї Метка ДДДДДДДВДДДДДДДД>і последовательность ГДДДДДДДДДД> і і цифр і ^ і АДДДДДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДї і АДДДДДДДДДДД>іидентификаторГДДДДДДДДДДДДЩ АДДДДДДДДДДДДДЩ Как расширение стандартного Паскаля, Borland Pascal позволя- ет использовать в качестве меток идентификаторы функций. Строки символов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Строка символов представляет собой последовательность, со- держащую ноль и более символов из расширенного набора символов кода ASCII, записанную в одной строке программы и заключенную в одиночные кавычки (апострофы). Строка символов, ничего не содер- жащая между апострофами, называется нулевой строкой. Два последо- вательных апострофа в строке символов обозначают один символ - апостроф. Атрибут длины строки символов выражается действительным количеством символов между апострофами, например: 'Borland' 'You'll see' '''' ';' ' ' '' { пустая строка } ' ' { пробел } В качестве расширения стандартного Паскаля, Borland Pascal разрешает вставлять в строку символов управляющие символы. Символ # с целой константой без знака в диапазоне от 0 до 255 обозначает соответствующий этому значению символ в коде ASCII. Между симво- лом # и целой константой не должно быть никаких разделителей. Аналогично, если несколько управляющих символов входит строку символов, то между ними не должно быть разделителей. Приведем несколько примеров строк символов: #13#10 'Line 1'#13'Line2' #7#7'Make up!'#7#7 ЪДДДДДДДДДДДДДДДДДДДДДДї строка символов ДДДДВДД>і строка в кавычках ГДДДВДВ> ^ і АДДДДДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДДДДДї і і і АДД>і управляющая строка ГДДДЩ і і АДДДДДДДДДДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДї ЪДДДї строка ДДДДДД>і ' ГДДДДДДДДДДДДДДВДДДД>і ' ГДДДД> в кавычках АДДДЩ ^ ЪДДДДДДї і АДДДЩ АДДґсимволі<ДЩ істрокиі АДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДДДДДї символ строки ДДДВДД>ілюбой символ, кроме ' ГДДДДДДД> і і или CR і ^ і АДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДї ЪДДДї і АДДДДДДД>і ' ГДДДДДД>і ' ГДДДДДЩ АДДДЩ АДДДЩ ЪДДДї ЪДДДДДДДДДДДДДДДДДДДї символ строки ДДДДДД>і # ГД>і беззнаковое целое ГДВДД> ^ АДДДЩ АДДДДДДДДДДДДДДДДДДДЩ і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Примечание: CR - символ возврата каретки. Длина символьной строки - это фактическое число символов в строке. Строка символов любой длины совместима с любым строковым типом и, при разрешении директивой {$X+} расширенного синтаксиса, с типом PChar.. Кроме того, строка символов с длиной, равной 1, совместима с любым типом Char. Строка символов длиной n, где n больше или равен 1, допустима для любого строкового типа и упако- ванных массивов из n символов. Комментарии ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Следующие конструкции представляют собой комментарии и поэ- тому игнорируются компилятором: { любой текст, не содержащий правую фигурную скобку } (* любой текст, не содержащий звездочку/правую круглую скобку *) Комментарий, содержащий знак доллара ($) сразу после откры- вающей скобки { или (*, является директивой компилятора. За сим- волом $ следует мнемоника команды компилятора. Примечание: Общее описание директив компилятора дано в Главе 2 "Справочного руководства программиста". Строки программы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В Borland Pascal строки программы имеют максимальную длину в 126 символов. Глава 3. Константы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Константа - это идентификатор, отмечающий значение, которое не может изменяться. Идентификатор константы не может быть вклю- чен в свое собственное описание. описание константы і ЪДДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДї ЪДДДї АДДДДД>іидентификаторГДДД>і = ГДД>іконстантаГДДД>і ; ГДВДД> ^ АДДДДДДДДДДДДДЩ АДДДЩ АДДДДДДДДДЩ АДДДЩ і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Идентификатор константы с предшествующим ему знаком обозна- чает значение целого или вещественного типа. Являясь расширением стандартного Паскаля, Borland Pascal позволяет использовать выражения-константы. Выражение-константа представляет собой выражение, которое может вычисляться компиля- тором без необходимости выполнения программы. Приведем примеры выражений-констант: 100 'A' 256 - 1 (2.5 + 1) / (2.5 - 1) 'Borland' + '' + 'Pascal' Chr(32) Ord('Z') - Ord('A') + 1 Простейший случай выражения-константы представляет собой простая константа, например 100 или 'A'. В стандартном Паскале допускается использовать только простые константы. В Borland Pascal разрешено использование выражений-констант. ЪДДДДДДДДДї константа ДДДД>івыражениеГДДД> АДДДДДДДДДЩ Поскольку компилятор должен иметь возможность полностью вы- числить выражение-константу во время компиляции, в качестве выра- жений-констант не допускается использовать следующие конструкции: - ссылки на переменные и типизированные константы (кроме констант в адресных выражениях, описываемых в Главе 5); - вызовы функций (кроме тех, которые отмечены далее); - оператор получения адреса @ (кроме констант в адресных вы- ражениях, описываемых в Главе 5). За исключением этих ограничений для выражений-констант соб- людаются те же синтаксические правила, что и для обычных выраже- ний (описанных в Главе 6 "Выражения"). В выражениях-константах допускается использовать следующие стандартные функции: Abs, Chr, Hi, High, Length, Lo, Low, Odd, Ord, Pred, Ptr, Round, SizeOf, Succ, Swap, Trunc. Приведем некоторые примеры использования выражений-констант в описаниях констант: const Min = 0; Max = 100; Center = (Max - Min) div 2; Beta = Chr(255); NumChars = Ord('Z') - Ord('A') + 1; Message = 'Out of memory'; ErrStr = 'Error:' + Message + '.'; ErrPos = 80 - Length(Error) div 2; ErrAttr = Blink + Red * 16 + White; Ln10 = 2.302585092994095684; Ln10R = 1 / Ln10; Numeric = ['0'..'9']; Alpha = ['A'..'Z','a'..'z']; AlphaNum = Alpha + Numeric; Глава 4. Типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД При описании переменной необходимо указать ее тип. Тип пере- менной описывает набор значений, которые она может принимать, и действия, которые могут быть над ней выполнены. Описание типа оп- ределяет идентификатор, который обозначает этот тип. ЪДДДДДДДДДДДДДДДї ЪДДДї ЪДДДДДї ЪДДДї описание ДД>і идентификатор ГДД>і = ГДД>і тип ГДД>і ; ГДД> типа АДДДДДДДДДДДДДДДЩ АДДДЩ АДДДДДЩ АДДДЩ Указание идентификатора в левой части описания типа означа- ет, что он определен как идентификатор типа для блока, в котором указано это описание типа. Область действия идентификатора типа не включает его самого, исключение составляют типы "указатель" (которые называют также ссылочными типами). ЪДДДДДДДДДДДДДДДДДДДДї тип ДДДДДДДДВДДДД>і простой тип іДДДДДДДДД> і АДДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і строковый тип ГДДДДґ і АДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і ссылочный тип ГДДДДґ і АДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і структурный тип ГДДДДґ і АДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і процедурный тип ГДДДДґ і АДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДї і АДДДД>і идентификатор типа ГДДДДЩ АДДДДДДДДДДДДДДДДДДДДЩ Имеется пять следующих основных классов типов. Они описыва- ются в следующем разделе. Простые типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Простые типы определяют упорядоченные множества значений. ЪДДДДДДДДДДДДДДДДДДДї простой тип ДДДДДВДДДД>і порядковый тип ГДДДДДДДДД> і АДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДї і АДДДД>і вещественный тип ГДДДДДЩ АДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДДДї вещественный тип ДДДДД>і идентификатор ГДДДДД> і вещественного типа і АДДДДДДДДДДДДДДДДДДДДЩ Идентификатор вещественного типа относится к числу стандарт- ных идентификаторов, которые могут быть вещественными, с одинар- ной точностью, с двойной точностью, с повышенной точностью и сложными. Примечание: В разделах "Числа" и "Строковые константы" Главы 2 вы можете найти описание того, как обозначать конс- танты целого и вещественного типов. Порядковые типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Порядковые типы представляют собой подмножество простых ти- пов. Все простые типы, отличные от вещественных типов, являются порядковыми и выделяются по следующим четырем характеристикам. - Все возможные значения данного порядкового типа представ- ляют собой упорядоченное множество, и каждое возможное значение связано с порядковым номером, который представ- ляет собой целочисленное значение. За исключением значе- ний целочисленного типа, первое значение любого порядко- вого типа имеет порядковый номер 0, следующее значение имеет порядковый номер 1 и так далее для каждого значения в этом порядковом типе. Порядковым номером значения цело- численного типа является само это значение. В любом по- рядковом типе каждому значению, кроме первого, предшест- вует другое значение, и после каждого значения, кроме последнего, следует другое значение в соответствии с упо- рядоченностью типа. - К любому значению порядкового типа можно применить стан- дартную функцию Ord, возвращающую порядковый номер этого значения. - К любому значению порядкового типа можно применить стан- дартную функцию Pred, возвращающую предшествующее этому значению значение. Если эта функция применяется к первому значению в этом порядковом типе, то выдается сообщение об ошибке. - К любому значению порядкового типа можно применить стан- дартную функцию Succ, возвращающую следующее за этим зна- чением значение. Если эта функция применяется к последне- му значению в этом порядковом типе, то выдается сообщение об ошибке. - К любому значению порядкового типа и к ссылке на перемен- ную порядкового типа можно применить стандартную функцию Low, возвращающую наименьшее значение в диапазоне данного порядкового типа. - К любому значению порядкового типа и к ссылке на перемен- ную порядкового типа можно применить стандартную функцию High, возвращающую наибольшее значение в диапазоне данно- го порядкового типа. Синтаксис порядкового типа имеет следующий вид: ЪДДДДДДДДДДДДДДДДДДДДї порядковый ДДДДДВДДДД>і отрезок типа ГДДДДДДДДД> тип і АДДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і перечислимый тип ГДДДДДґ і АДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДї і АДДДД>і идентификатор ГДДДДДЩ і порядкового типа і АДДДДДДДДДДДДДДДДДДДДЩ Borland Pascal имеет 10 встроенных порядковых типов: Integer (целое), Shortint (короткое целое), Longint (длинное целое), Byte (длиной в байт), Word (длиной в слово), Boolean (булевское), ByteBool (булевское размером в байт), WordBool (булевское разме- ром в слово), LongBool (длинный булевский тип) и Char (символьный тип). Кроме того, имеется два других класса определяемых пользо- вателем порядковых типов: перечислимые типы и отрезки типов (под- диапазоны). Целочисленные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В Borland Pascal имеется пять предопределенных целочисленных типов: Shortint (короткое целое), Integer (целое), Longint (длин- ное целое), Byte (длиной в байт) и Word (длиной в слово). Каждый тип обозначает определенное подмножество целых чисел, как это по- казано в следующей таблице. Предопределенные целочисленные типы Таблица 4.1 ЪДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДї і Тип і Диапазон і Формат і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ і короткое целое і -128 .. 127 і 8 бит со знаком і і (Shortint) і і і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ і целое і -32768 .. 32767 і 16 бит со знаком і і (Integer) і і і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ і длинное целое і -2147483648 .. і 32 бита со знаком і і (Longint) і ..2147483647 і і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ і длиной в байт і 0 .. 255 і 8 бит без знака і і (Byte) і і і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ і длиной в слово і 0 .. 65535 і 16 бит без знака і і (Word) і і і АДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДЩ Арифметические действия над операндами целочисленного типа предполагают 8-битовую, 16-битовую и 32-битовую точность в соот- ветствии со следующими правилами: - Тип целой константы представляет собой встроенный целочис- ленный тип с наименьшим диапазоном, включающим значение этой целой константы. - В случае бинарной операции (операции, использующей два операнда), оба операнда преобразуются к их общему типу пе- ред тем, как над ними совершается действие. Общим типом является встроенный целочисленный тип с наименьшим диапа- зоном, включающим все возможные значения обоих типов. Нап- ример, общим типом для целого и целого длиной в байт явля- ется целое, а общим типом для целого и целого длиной в слово является длинное целое. Действие выполняется в соот- ветствии с точностью общего типа и типом результата явля- ется общий тип. - Выражение справа в операторе присваивания вычисляется не- зависимо от размера или типа переменной слева. - Любые операнды размером в байт преобразуются к промежуточ- ному операнду размером в слово, который совместим перед выполнением арифметической операции с типами Integer и Word. Значение одного целочисленного типа может быть явным образом преобразовано к другому целочисленному типу с помощью приведения типов. Примечание: Приведение типов описывается в Главах 5 и 6. Булевские типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Существует 4 предопределенных булевских типа: Boolean, ByteBool, WordBool и LongBool. Значения булевского типа обознача- ются встроенными идентификаторами констант False и True. Посколь- ку булевский тип является перечислимым, между этими значениями имеют место следующие отношения: - False < True - Ord(False) = 0 - Ord(True) = 1 - Succ(False) = True - Pred(True) = False Переменные типа Boolean и ByteBool занимают 1 байт, пере- менная WordBool занимает два байта (слово), а переменная LongBool занимает четыре байта (два слова). Boolean - это наиболее предпо- чтительный тип, использующей меньше памяти; типа ByteBool, WordBool и LongBool обеспечивают совместимость с другими языками и средой Windows. Предполагается, что переменная типа Boolean имеет порядковые значения 0 и 1, но переменные типа ByteBool, WordBool и LongBool могут иметь другие порядковые значения. Когда выражение типа ByteBool, WordBool или LongBool равна 1, то подразумевается, что она имеет значение True, а если оно равно 0 - то False. Когда значение типа ByteBool, WordBool или LongBool используется в кон- тексте, где ожидается значение Boolean, компилятор будет автома- тически генерировать код, преобразующий любое ненулевое значение в значение True. Символьный тип (char) ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Множеством значений этого типа являются символы, упорядочен- ные в соответствии с расширенным набором символов кода ASCII. При вызове функции Ord(Ch), где Ch - значение символьного типа, возв- ращается порядковый номер Ch. Строковая константа с длиной 1 может обозначать значение константы символьного типа. Любое значение символьного типа может быть получено с помощью стандартной функции Chr. Перечислимые типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Перечислимые типы определяют упорядоченные множества значе- ний через перечисление идентификаторов, которые обозначают эти значения. Упорядочение множеств выполняется в соответствии с пос- ледовательностью, в которой перечисляются идентификаторы. ЪДДДї ЪДДДДДДДДДДДДДДДї ЪДДДї перечислимый ДД>і ( ГДДД>і список ГДДД>і ) ГДДД> тип АДДДЩ іидентификаторові АДДДЩ АДДДДДДДДДДДДДДДЩ список ЪДДДДДДДДДДДДДї идентификаторов ДДДДДДДД>іидентификаторГДДДВДДДД> ^ АДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДґ , і<ДДДДДДДДДДДЩ АДДДЩ При указании идентификатора в списке идентификаторов пере- числимого типа он описывается как константа для блока, в котором указано описание перечислимого типа. Типом этой константы являет- ся описанный перечислимый тип. Порядковый номер перечислимой константы определяется ее по- зицией в списке идентификаторов при описании. Перечислимый тип, в котором описывается константа, становится ее типом. Первая пере- числимая константа в списке имеет порядковый номер 0. Приведем пример перечислимого типа: type suit = (club, diamond, heart, spade); Согласно этим описаниям diamond является константой типа suit. При применении функции Ord к значению перечислимого типа Ord возвращает целое число, которое показывает, какое положение зани- мает это значение в отношении других значений этого перечислимого типа. Согласно предшествующим описаниям, Ord(club) возвращает 0, Ord(diamond) возвращает 1 и так далее. Отрезки типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Отрезок типа представляет собой диапазон значений из поряд- кового типа, называемого главным типом. Определение отрезка типа включает наименьшее и наибольшее значение в поддиапазоне. Оно имеет следующий синтаксис: отрезок ЪДДДДДДДДДДДї ЪДДДДї ЪДДДДДДДДДДДї типа ДДДДДДДДДДД>і константа ГДДД>і .. ГДДД>і константа ГДДД> АДДДДДДДДДДДЩ АДДДДЩ АДДДДДДДДДДДЩ Обе константы должны иметь один и тот же порядковый тип. От- резки типов, имеющие вид a..b, предполагают, что a меньше или равно b. Приведем примеры отрезков типов: 0..99 -128..127 club..heart Переменная отрезка типа имеет все свойства переменных глав- ного типа, однако ее значение на этапе выполнения должно принад- лежать указанному интервалу. Разрешение использования выражений-констант там, где стан- дартный Паскаль допускает только простые константы, приводит к некоторой синтаксической неоднозначности. Рассмотрим следующие описания: const X = 50; Y = 10; type Color = (Red, Green, Blue); Scale = (X - Y) * 2..(X + Y) * 2; Согласно синтаксису стандартного Паскаля, если определение типа начинается с круглой скобки, то это перечислимый тип (такой как Color в данном примере). Однако Scale предназначен для опре- деления отрезка типа. Решение состоит в том, чтобы переупорядо- чить первое выражение поддиапазона или задать другую константу, равную значению данного выражения, и использовать эту константу в определении типа: type Scale = 2 * (X - Y)..(X + Y); Вещественные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД К вещественному типу относится подмножество вещественных чи- сел, которые могут быть представлены в формате с плавающей точкой с фиксированным числом цифр. Запись значения в формате с плаваю- щей запятой обычно включает три значения - m, b и e - таким обра- зом, что m x b^e=n, где b всегда равен 2, а m и e являются цело- численными значениями в диапазоне вещественного типа. Эти значения m и e далее определяют диапазон представления и точность вещественного типа. Имеется пять видов вещественных типов: вещественное (Real), с одинарной точностью (Single), с двойной точностью (Double), с повышенной точностью (Extended) и сложное (Comp). Действия над типами с одинарной точностью, с двойной точностью и с повышенной точностью и над сложным типом могут выполняться только при нали- чии числового сопроцессора 8087 (который был описан ранее). Вещественные типы различаются диапазоном и точностью связан- ных с ними значений (см. Таблицу 4.2). Диапазон представления и десятичные цифры для вещественных типов Таблица 4.2 ЪДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДї і Тип і Диапазон і Цифры і ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ і вещественное і2.9x10^-39 .. 1.7x10^38 іот 11 до 12і і (Real) і і і ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ і с одинарной точностью і1.5x10^-45 .. 3.4x10^38 іот 7 до 8 і і (Single) і і і ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ і с двойной точностью і5.0x10^-324 .. 1.7x10^308 іот 15 до 16і і (Double) і і і ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ і с повышенной точностьюі1.9x10^-4951 .. 1.1x10^4932іот 19 до 20і і (Extended) і і і ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДґ і сложный тип і -2^63 + 1 .. 2^63 - 1 і і і (Comp) і і і АДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДЩ Примечание: Сложный тип содержит только целочисленные значения в диапазоне от -2^63+1 до 2^63-1, что приблизи- тельно равно -9.2x10^18 и 9.2x10^18. Borland Pascal поддерживает две модели генерации кода для выполнения действий над вещественными типами: программную для чи- сел с плавающей точкой и аппаратную для чисел с плавающей точкой. Выбор соответствующей модели осуществляется с помощью директивы компилятора $N. Программная поддержка чисел с плавающей точкой ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В состоянии {$N-}, которое устанавливается по умолчанию, ге- нерируемый код выполняет все вычисления с вещественными типами программно, через вызов подпрограмм библиотеки исполняющей систе- мы. Из-за соображений скорости и размера кода в этом состоянии допускаются только действия над переменными типа real (веществен- ное). Любая попытка оттранслировать операторы, выполняющие дейс- твия над типами с одинарной точностью, с двойной точностью, с по- вышенной точностью и над сложными типами, вызовет сообщение об ошибке. Аппаратная поддержка чисел с плавающей точкой ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В состоянии {$N+} генерируемый код выполняет все вычисления над вещественными типами с помощью числового сопроцессора 8087. Это состояние позволяет использовать все пять вещественных типов, однако оно требует наличия сопроцессора 8087 на этапе компиляции и выполнения. Borland Pascal включает в себя библиотеки исполняющей систе- мы, которые автоматически эмулируют программным путем сопроцессор 80х87, если при выполнении прикладной программы DOS реального или защищенного режима он отсутствует. Для определения того, следует ли в программу DOS включить эмулятор сопроцессора 80x87, исполь- зуется директива компилятора $E. Если вы создает прикладную прог- рамму для реального или защищенного режима DOS, и сопроцессор 80х87 отсутствует, разрешение директивы компилятора $E обеспечи- вает полную программную эмуляцию сопроцессора 80x87. Для программ Windows директива $E не действует, так как Windows обеспечивает собственные подпрограммы эмуляции. Примечание: Более детальное описание генерации кода при аппаратной поддержке чисел с плавающей запятой вы може- те найти в Главе 15 "Использование сопроцессора 8087 в Borland Pascal". Строковые типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Значением строкового типа является последовательность симво- лов с динамическим атрибутом длины (в зависимости от действитель- ного числа символов при выполнении программы) и постоянным атри- бутом размера в диапазоне от 1 до 255. Текущее значение атрибута длины можно получить с помощью стандартной функции Length. ЪДДДДДДї строковый тип ДДД>іstringГДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД> АДДДДДДЩ і ^ і ЪДДДї ЪДДДДДї ЪДДДї і АД>і [ ГДД>іцелоеГДД>і ] ГДЩ АДДДЩ і без і АДДДЩ ізнакаі АДДДДДЩ Примечание: Операторы работы со строковыми типами опи- сываются разделах "Строковые операторы" и "Операторы отно- шений" Главы 6. Отношение между любыми двумя строковыми значениями устанав- ливается согласно отношению порядка между значениями символов в соответствующих позициях. В двух строках разной длины каждый сим- вол более длинной строки без соответствующего символа в более ко- роткой строке принимает значение "больше"; например, 'Xs' больше, чем 'X'. Нулевые строки могут быть равны только другим нулевым строкам, и они являются наименьшими строковыми значениями. Примечание: Стандартные процедуры и функции для работы со строковыми типами описаны в разделе "Строковые процедуры и функции". К символам в строках можно обращаться как к элементам масси- ва. См. раздел "Массивы, строки и индексы" в Главе 5. К идентификатору строкового типа и к ссылке на переменную строкового типа можно применять стандартные функции Low и High. В этом случае функция Low возвращает 0, а High возвращает атрибут размера (максимальную длину) данной строки. Параметр-переменная, описанная с помощью идентификатора OpenString и ключевого слова string в состоянии {$P+}, является открытым строковым параметром. Открытые строковые параметры поз- воляют передавать одной и той же процедуре или функции строковые переменные изменяющегося размера. Примечание: Открытые строковые параметры описываются в Главе 9. Структурные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Структурный тип, характеризуемый методом структурирования и типами своих компонентов, имеет более одного значения. Если тип компонента является структурным, то получаемый в результате структурный тип имеет более одного уровня структурирования. Структурный тип может иметь неограниченные уровни структурирова- ния. ЪДДДДДДДДДДДДДДДї структурный ДДВДДДДДДДДДДДДДДДДВДД>і тип массив ГДДДДД> тип і ЪДДДДДДДДї ^ і АДДДДДДДДДДДДДДДЩ ^ АД>і packed ГДЩ і ЪДДДДДДДДДДДДДДДї і АДДДДДДДДЩ ГДД>і множественный ГДДґ і і тип і і і АДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДї і ГДД>і файловый тип ГДДґ і АДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДї і ГДД>і тип "запись" ГДДґ і АДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДї і АДД>і объектный тип ГДДЩ АДДДДДДДДДДДДДДДЩ Слово packed (упакованный) в описании структурного типа тре- бует от компилятора уплотнить хранимые данные, даже за счет уменьшения скорости доступа к компоненту в переменной этого типа. Слово packed не имеет никакого действия в Borland Pascal, пос- кольку упаковка выполняется здесь автоматически всюду, где это возможно. Типы массив ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Массивы содержат фиксированное число элементов одного типа, так называемого типа элемента. На приводимой ниже синтаксической диаграмме тип элемента следует за словом of. ЪДДДДДДДї ЪДДДї ЪДДДДДДДї ЪДДДї ЪДДДДї ЪДДДДДї тип ДД>і array ГД>і [ ГДДД>і тип ГДВД>і ] ГД>і of ГД>і тип Г> массив АДДДДДДДЩ АДДДЩ ^ іиндексаі і АДДДЩ АДДДДЩ АДДДДДЩ і АДДДДДДДЩ і і ЪДДДї і АДДДДґ , і<ДДЩ АДДДЩ тип ЪДДДДДДДДДДДДДДДДї индекса ДДД>і порядковый тип ГДДД> АДДДДДДДДДДДДДДДДЩ В индексных типах, по одному для каждой размерности массива, указывается число элементов. Допустимыми индексными типами явля- ются все порядковые типы, за исключением длинного целого и подди- апазонов длинного целого. Массив может быть проиндексирован по каждой размерности всеми значениями соответствующего индексного типа; число элементов поэтому равно числу значений в каждом ин- дексном типе. Число размерностей не ограничено. Приведем пример типа массив: array[1..100] of Real Если тип элемента в типе массив также является массивом, то результат можно рассматривать как массив массивов или как один многомерный массив. Например, array[boolean] of array[1..100] of array[Size] of Real интерпретируется компилятором точно так же, как массив: array[boolean,1..10,Size] of Real Кроме того, можно записать выражение: packed array[1..10] of packed array[1..8] of Boolean как packed array[1..10,1..8] of Boolean Для доступа к элементам массива необходимо указать идентифи- катор массива с одним или несколькими индексами в скобках (см. раздел "Массивы, строки и индексы"). Тип массив, имеющий вид: packed array[M..N] of Char где M меньше N, называется упакованным строковым типом (слово packed можно опустить, поскольку оно не оказывает действия в Borland Pascal). Упакованный строковый тип имеет некоторые свойс- тва, не характерные для других типов массив (см. раздел "Тождест- венные и совместимые типы" далее в этой главе). Массив вида: array[0..X] of Char где X - положительное целое число, называется массивом с нулевой базой. Массивы с нулевой базой используются для хранения строк с завершающим нулем, и, когда разрешен расширенный синтаксис (с по- мощью директивы компилятора {$X+}), символьный массив с нулевой базой совместим со значением типа PChar. Полностью эта тема об- суждается в Главе 18 "Использование строк с завершающим нулем". Параметр, описанный с помощью синтаксиса array of T, называ- ется открытым строковым параметром. Открытые строковые параметры позволяют передавать одной и той же процедуре или функции строко- вые переменные изменяющегося размера. Примечание: Открытые строковые параметры описываются в Главе 9. Типы запись ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Тип запись содержит установленное число элементов или полей, которые могут быть различных типов. Описание типа запись указыва- ет тип каждого поля и идентификатор, который именует поле. ЪДДДДДДДДї ЪДДДДДї тип запись ДДД>і record ГДДВДДДДДДДДДДДДДДДД>і end ГДД> АДДДДДДДДЩ і ЪДДДДДДДДї ^ АДДДДДЩ АД>і список ГДЩ і полей і АДДДДДДДДЩ список ЪДДДДДДДДДДДДї полейВД>і фиксирован-ГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДД> і і ная часть і і ЪДДДї ЪДДДДДДДДДДДДї ^ і ЪДДДї ^ і АДДДДДДДДДДДДЩ АД>і ; ГДДД>і вариантная ГДЩ АД>і ; ГДЩ і АДДДЩ ^ і часть і АДДДЩ АДДДДДДДДДДДДДДДДДДДДДДДДДДЩ АДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДї ЪДДДї ЪДДДДДї фиксированная ДДДД>і список ГДД>і : ГДДД>і тип ГДДВДД> часть ^ і идентификаторов і АДДДЩ АДДДДДЩ і і АДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДї і АДДДДДДДДДДДДґ ; і<ДДДДДДДДДДДДДДДДДДДДДДДДЩ АДДДЩ Фиксированная часть типа запись содержит список фиксирован- ных полей вместе с идентификатором и типом для каждого поля. Каж- дое поле содержит информацию, которая всегда отыскивается одним и тем же способом. Приведем пример типа запись: record year: integer; { год } month: 1..12; { месяц } day: 1..31; { число } end В вариантной части, изображенной на синтаксической диаграмме описания типа запись, память распределяется более чем для одного списка полей, поэтому доступ к информации может быть осуществлен более чем одним способом. Каждый список полей является вариантом. Варианты налагаются друг на друга в памяти, поэтому в любое время возможен доступ ко всем полям во всех вариантах. вариантная часть і ЪДДДДї ЪДДДДДДДДї ЪДДї ЪДДДДДДДї АД>іcaseГДВДДДДДДДДДДДДДДДДДДД>ітип поляГД>іofГДДДД>івариантГДВ> АДДДДЩ і ^ іпризнакаі АДДЩ ^ АДДДДДДДЩ і і ЪДДДДДДДї ЪДДДї і АДДДДДДДДЩ і ЪДДДї і А>іиденти-Г>і : ГДЩ АДДДДґ ; і<ДДДЩ іфикаторі АДДДЩ АДДДЩ АДДДДДДДЩ ЪДДДДДДДДДДДДДДДДї тип поля ДДДД>і идентификатор ГДДДД> признака іпорядкового типаі АДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДї ЪДДДї ЪДДДї ЪДДДї вариант ДДДД>іконстантаГДВД>і : ГД>і ( ГДВДДДДДДДДДДДДД>і ) ГДД> ^ АДДДДДДДДДЩ і АДДДЩ АДДДЩ і ^ АДДДЩ і ЪДДДї і і і АДДДДґ , і<ДДДДЩ і ЪДДДДДДї і АДДДЩ АД>ісписокГДЩ іполей і АДДДДДДЩ Вы можете видеть на диаграмме, что каждый вариант идентифи- цирован по крайней мере одной константой. Все константы должны быть отличными друг от друга и иметь порядковый тип, совместимый с типом поля признака. Доступ к вариантным и фиксированным полям один и тот же. В вариантной части можно указать необязательный идентифика- тор - идентификатор признака поля. При наличии идентификатора признака поля он становится идентификатором дополнительного фик- сированного поля записи - поля признака. Программа может исполь- зовать значение поля признака для указания, какой вариант являет- ся активным в настоящий момент. Без указания поля признака программа выбирает вариант по другому критерию. Ниже приводятся несколько примеров типов запись: record firstName,lastName : string[40]; birthDate : Date; case citizen : boolean of True : (birthPlace: string[40]); False : (country : string[20]; entryPort : string[20]; entryDate : Date; exitDate : Date); end record x,y : real; case kind : Figure of rectangle : (height,wigth: real); { прямоугольник } triangle : (size1,side2,angle: real); { треугольник } circle : (radius: real); { круг } end Объектные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Объектный тип является структурой, состоящей из фиксирован- ного числа компонентов. Каждый компонент является либо полем, со- держащим данные строго определенного типа, либо методом, выполня- ющим операции над объектом. По аналогии с описанием переменных, описание поля указывает тип данного этого поля и идентификатор, именующий поле: по аналогии с описанием процедуры или функции, описание метода указывает заголовок процедуры, функции, конструк- тора или деструктора. Объектный тип может наследовать компоненты другого объектно- го типа. Если T2 наследует от T1, то T2 является потомком T1, а T1 является родителем T2. Наследование является транзитивным, то есть если T3 наследу- ет от T2, а T2 наследует от T1, то T3 наследует от T1. Область (домен) объектного типа состоит из него самого и из всех его нас- ледников. ЪДДДДДДї ЪДДДДДДДДДДДДДДДДї тип объектаДД>іobjectГДВДДДДДДДДДДДДДДДДДДД>ісписок компонентГДї АДДДДДДЩ і ЪДДДДДДДДДДДДї ^ АДДДДДДДДДДДДДДДДЩ і АД>іHаследованиеГДЩ і АДДДДДДДДДДДДЩ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і ЪДДДї АДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДґendГ> і ЪДДДДДДДї ЪДДДДДДДДДДДДДДДДї і АДДДЩ АДД>іprivateГДД>ісписок компонентГДЩ АДДДДДДДЩ АДДДДДДДДДДДДДДДДЩ ЪДДДї ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї ЪДДДї наследование ДД>і ( ГД>іидентификатор объектного типаГД>і ) ГДД> АДДДЩ АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ АДДДЩ список компонент ДДВДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДД> і ЪДДДДДДДДї ^ і ЪДДДДДДДДДї ^ АД>і список ГДДЩ АД>і список ГДДЩ і полей і і методов і АДДДДДДДДЩ АДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДДДДДї ЪДДДї ЪДДДДї ЪДДДї список полей ДДД>іcписок идентификаторовГД>і : ГД>іtypeГ>і ; ГВ> ^ АДДДДДДДДДДДДДДДДДДДДДДЩ АДДДЩ АДДДДЩ АДДДЩі і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДї ЪДДДї список методов ДД>ізаголовокГДВДДДДДДДДДДДДДДДДДДДДДДДДДДґ ; ГВД> ^ і метода і і ЪДДДї ЪДДДДДДДї ^АДДДЩі і АДДДДДДДДДЩ А>і ; ГД>іvirtualГВДДДДДДДЩ і і АДДДЩ АДДДДДДДЩі ^ і і і АДДДДДДДДїі і і ЪДДДДДДДДДїіі і А>і целая ГЩі і іконстантаі і і АДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДДДДДДДї заголовок метода ДДДДВДДД>і заголовок процедуры ГДДДДДД> і АДДДДДДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДДДДДДї і ГДДД>і заголовок функции ГДДґ і АДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДДї і ГДДД>і заголовок конструктора ГДДґ і АДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДДї і АДДД>і заголовок деструктора ГДДЩ АДДДДДДДДДДДДДДДДДДДДДДДДЩ Следующий исходный код приводит пример описания объектного типа. Далее во всей этой главе на данное описание будут делаться ссылки. type Point = object X, Y: integer; end; Rect = object A, B: TPoint; procedure Init(XA, YA, XB, YB: Integer); procedure Copy(var R: TRectangle); procedure Move(DX, DY: Integer); procedure Grow(DX, DY: Integer); procedure Intersect(var R: TRectangle); procedure Union(var R: TRectangle); function Contains(P: Point): Boolean; end; StringPtr = ^String; FieldPtr = ^TField; TField = object X, Y, Len: Integer; Name: StringPtr; constructor Copy(var F: TField); constructor Init(FX, FY, FLen: Integer; FName: String); destructor Done; virtual; procedure Display; virtual; procedure Edit; virtual; function GetStr: String; virtual; function PutStr(S: String): Boolean; virtual; end; StrFieldPtr = ^TStrField; StrField = object(TField) Value: PString; constructor Init(FX, FY, FLen: Integer; FName: String); destructor Done; virtual; function GetStr: String; virtual; function PutStr(S: String): Boolean; virtual; function Get: string; procedure Put(S: String); end; NumFieldPtr = ^TNumField; TNumField = object(TField) private Value, Min, Max: Longint; public constructor Init(FX, FY, FLen: Integer; FName: String; FMin, FMax: Longint); function GetStr: String; virtual; function PutStr(S: String): Boolean; virtual; function Get: Longint; function Put(N: Longint); end; ZipFieldPtr = ^TZipField; ZipField = object(TNumField) function GetStr: String; virtual; function PutStr(S: String): Boolean; virtual; end; В отличие от других типов, объектные типы могут описываться только в разделе описаний типов, находящемся на самом внешнем уровне области действия программы или модуля. Таким образом, объ- ектные типы не могут описываться в разделе описаний переменных или внутри блока процедуры, функции или метода. Тип компоненты файлового типа не может иметь объектный тип или любой структурный тип, содержащий компоненты объектного типа. Компоненты и область действия ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Область действия идентификатора компоненты простирается за пределы объектного типа. Более того, область действия идентифика- тора компонента простирается сквозь блоки процедур, функций, конструкторов и деструкторов, которые реализуют методы объектного типа и его наследников. Исходя из этих соображений, написание идентификатора компоненты должно быть уникальным внутри объектно- го типа и внутри всех его наследников, а также внутри всех его методов. Область действия идентификатора компонента, описанного в части private описания типа, ограничивается модулем (программой), которая содержит описание объектного типа. Другими словами, част- ные (private) компоненты-идентификаторы действуют, как обычные общедоступные идентификаторы в рамках модуля, который содержит описание объектного типа, а вне модуля любые частные компоненты и идентификаторы неизвестны и недоступны. Поместив в один модуль связанные типы объектов, можно сделать так, что эти объекты смо- гут обращаться к частным компонентам друг друга, и эти частные компоненты будут неизвестны другим модулям. В описании объектного типа заголовок метода может задавать параметры описываемого объектного типа, даже если описание еще не полное. Это иллюстрируется методами Copy, Intersect и Union типа TRectange в предыдущем примере. Методы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание метода внутри объектного типа соответствует опере- жающему описанию метода (forward). Таким образом, где-нибудь пос- ле описания объектного типа, но внутри той же самой области дейс- твия, что и область действия описания объектного типа, метод дол- жен реализоваться путем определения его описания. Если требуется уникальный идентификатор метода, то использу- ется уточненный идентификатор метода. Он состоит из идентификато- ра типа объекта, за которым следуют точка и идентификатор метода. Как и любому другому идентификатору, идентификатору уточненного метода, если требуется, могут предшествовать идентификатор пакета и точка. уточненный идентификатор метода і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДДДДДДДДДДДї АД>іидентификатор объектного типаГ>і . Г>іидентификатор методаГ> АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ АДДДЩ АДДДДДДДДДДДДДДДДДДДДЩ Виртуальные методы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД По умолчанию, методы являются статическими, однако они мо- гут, за исключением конструкторов, быть виртуальными (посредством включения директивы virtual в описание метода). Компилятор разре- шает ссылки на вызовы статических методов во время процесса ком- пиляции, тогда как вызовы виртуальных методов разрешаются во вре- мя выполнения. Это иногда называют поздним связыванием. Если объектный тип объявляет или наследует какой-либо вирту- альный метод, то переменные этого типа должны быть инициализиро- ваны посредством вызова конструктора перед вызовом любого вирту- ального метода. Таким образом, объектный тип, который описывает или наследует виртуальный метод, должен также описывать или нас- ледовать по крайней мере один метод-конструктор. Объектный тип может переопределять любой из методов, которые он наследует от своих родителей. Если описание метода в потомке указывает тот же идентификатор метода, что и описание метода в родителе, то описание в потомке переопределяет описание в родите- ле. Область действия переопределяющего метода расширяется до сфе- ры действия потомка, в котором этот метод был введен, и будет ос- таваться таковой, пока идентификатор метода не будет переопреде- лен снова. Переопределение статического метода не зависит от изменения заголовка метода. В противоположность этому, переопределение вир- туального метода должно сохранять порядок, типы и имена парамет- ров, а также типы результатов функций, если таковые имеются. Бо- лее того, переопределение опять же должно включать директиву virtual. Динамические методы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Borland Pascal поддерживает дополнительные методы с поздним связыванием, которые называются динамическими методами. Динами- ческие методы отличаются от виртуальных только характером их дис- петчеризации на этапе выполнения. Во всех других отношениях дина- мические методы считаются эквивалентными виртуальным. Описание динамического метода эквивалентно описанию вирту- ального метода, но описание динамического метода должно включать в себя индекс динамического метода, который указывается непос- редственно за ключевым словом virtual. Индекс динамического мето- да должен быть целочисленной константой в диапазоне от 1 до 656535 и должен быть уникальным среди индексов других динамичес- ких методов, содержащихся в объектном типе или его предках. Нап- ример: procedure FileOpen(var Msg: TMessage); virtual 100; Переопределение динамического метода должно соответствовать порядку, типа и именам параметров и точно соответствовать типу результата функции порождающего метода. Переопределение также должно включать в себя директиву virtual, за которой следует тот же индекс динамического метода, который был задан в объектном ти- пе предка. Примечание: Подробнее о динамических методах и о раз- нице в диспетчеризации динамических и виртуальных методов рассказывается в Главе 22. Создание экземпляров объектов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Экземпляр объекта создается посредством описание переменной или константы объектного типа или путем применения стандартной процедуры New к переменной типа указатель на объектный тип. Ре- зультирующий объект называется экземпляром объектного типа. var F: TField; Z: TZipField; FP: PField; ZP: PZipField; С учетом этих описание переменных F является экземпляром TField, а Z - экземпляром TZipField. Аналогично, после применения New к FP и ZP, FP будет указывать на экземпляр TField, а ZP - на экземпляр TZipField. Если объектный тип содержит виртуальные методы, то экземпля- ры этого объектного типа должны инициализироваться посредством вызова конструктора перед вызовом любого виртуального метода. Ни- же приведен пример: var S: StrField; begin S.Init (1, 1, 25, 'Первое имя'); S.Put ('Френк'); S.Display; ... S.Done; end; Если S.Init не вызывался, то вызов S.Display приведет к неу- дачному завершению данного примера. Присваивание экземпляра объектного типа не подразумевает инициализации экземпляра. Объект инициализируется кодом, генерируемым компилятором, который выполняется между вызовом конструктора, и когда выполне- ние фактически достигает первого оператора в блоке кода конструк- тора. Если экземпляр объекта не инициализируется, и проверка диа- пазона включена (директивой {$R+}), то первый вызов виртуального метода экземпляра объекта дает ошибку этапа выполнения. Если про- верка диапазона выключена (директивой {$R-}), то первый виртуаль- ного метода неинициализированного объекта может привести к неп- редсказуемому поведению. Правило обязательной инициализации применимо также к экземп- лярам, которые являются компонентами структурных типов. Например: var Comment: array [1..5] of TStrField; I: integer; begin for I := 1 to 5 do Comment [I].Init (1, I + 10, 40, 'первое_имя'); . . . for I := 1 to 5 do Comment [I].Done; end; Для динамических экземпляров инициализация, как правило, связана с размещением, а очистка - с удалением, что достигается благодаря расширенному синтаксису стандартных процедур New и Dispose. Например: var SP: StrFieldPtr; begin New (SP, Init (1, 1, 25, 'первое_имя'); SP^.Put ('Френк'); SP^.Display; . . . Dispose (SP, Done); end; Указатель на объектный тип является совместимым по присваи- ванию с указателем на любой родительский объектный тип, поэтому во время выполнения программы указатель на объектный тип может указывать на экземпляр этого типа или на экземпляр любого дочер- него типа. Например, указатель типа ZipFieldPtr может присваиваться указателям типа PZipField, PNumField и PField, а во время выпол- нения программы указатель типа PField может либо иметь значение nil, либо указывать на экземпляр TField, TNumField или TZipField, или на любой экземпляр дочернего по отношению к TField типа. Эти правила совместимости указателей по присваиванию приме- нимы также к параметрам-переменным объектного типа. Например, ме- тоду TField.Copy могут быть переданы экземпляры типов TField, TStrField, TNumField, TZipField или любые другие экземпляры до- чернего от TField типа. Активизация методов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Метод активизируется посредством оператора вызова процедуры или функции, состоящего из десигнатора метода, за которым следует список параметров. Такой тип вызова называется активизацией мето- да. десигнатор метода і ЪДДДДДДДДДДДДДДДДДДДДї АДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД>іидентификатор методаГ> і ^ АДДДДДДДДДДДДДДДДДДДДЩ і ЪДДДДДДДДДДДДДДДДДДДДДДї ЪДДДї і А>і ссылка на переменную Г>і . ГДДДДЩ АДДДДДДДДДДДДДДДДДДДДДДЩ АДДДЩ Ссылка на переменную задается, если десигнатор метода должен описывать экземпляр объектного типа, а идентификатор метода дол- жен обозначать метод этого объектного типа. Экземпляр, обозначенный десигнатором метода, становится не- явным фактическим параметром метода; он соответствует формальному параметру-переменной с именем Self, который владеет объектным ти- пом, соответствующим активизированному методу. Для статических методов описанный тип (на этапе компиляции) определяет, какой из методов активизируется. Например, десигнато- ры F.Init и FP^.Init всегда активизируют TField.Init, так как описанным типом F и FP^ является TField. Для виртуальных методов выбором экземпляра управляет факти- ческий тип (этапа выполнения). Например, десигнатор FP^.Display может активизировать методы TField.Display, TStrField.Display, TNumField.Display или TZipField.Display (в зависимости от факти- ческого типа экземпляра, указываемого FP). В операторе with, ссылающемся на экземпляр объектного типа, ссылка на переменную в десигнаторе метода может опускаться. В этом случае экземпляром, на который ссылается оператор with, ста- новится неявный параметр Self активизации метода. Аналогично, ссылка не переменную может опускаться в методе. В этом случае параметром Self метода, содержащего вызов, становится неявный па- раметр Self активизации метода. Активизация уточненных методов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В методе, операторе вызова функции или процедуры для обозна- чения активизации конкретного метода допускается использование десигнатора уточненного метода. Такой тип вызова называется акти- визацией уточненного метода. десигнатор уточненного метода і ЪДДДДДДДДДДДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДДДДДДДДДДДї АДВ>і идентификатор Г>і . ГДДДДДДД>іидентификатор методаГ> і і объектного типа і АДДДЩ ^ АДДДДДДДДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДї і А>і inherited ГДДДДДДДДДДЩ АДДДДДДДДДДДДДДДДДДДДДДЩ Объектный тип, заданный в десигнаторе уточненного метода, должен быть таким же, как и включающий метод объектный тип, или соответствовать родительскому типу. Для обозначения родительского объектного типа или объектного типа, включающего метод, можно использовать ключевое слово inherited; в методах объектного типа, не имеющего предка, ключе- вое слово inherited использоваться не может. Неявный параметр Self активизации уточненного метода стано- вится параметром Self метода, содержащего вызов. Активизация уточненных методов не предусматривает механизма диспетчеризации виртуальных методов - вызов будет всегда статическим и всегда вы- зывает заданный метод. Активизация уточненного метода используется обычно в переоп- ределяющем методе для активизации переопределяющего метода. С учетом описанных выше типов приведем некоторые примеры активиза- ции уточненных методов: constructor TNumField.Init(Fx, FY, Flen: Integer; FName: String; FMin, FMax: Longint); begin inherited Init(FX, FY, FLen, FName); Value := 0; Min := FMin; Max := FMax; end; function TZipField.PutStr(S: String): Boolean; begin PutStr := (Length(S) = 5) and TNumField.PutStr(S); end; Как показывают эти примеры, активизация уточненных методов позволяет переопределяющему методу "вновь использовать" код мето- да, который он переопределяет. Множественные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Диапазон значений множественного типа представляет собой мощность множества для определенного порядкового типа (базового типа). Каждое возможное значение множественного типа является подмножеством возможных значений базового типа. Переменная множественного типа может принимать как все зна- чения множества, так и ни одного. ЪДДДДДї ЪДДДДї ЪДДДДДДДДДДДДДДДДї тип множество ДДД>і set ГДДД>і of ГДДД>і порядковый тип ГДДД> АДДДДДЩ АДДДДЩ АДДДДДДДДДДДДДДДДЩ Базовый тип не должен иметь более 256 возможных значений, и порядковые значения верхней и нижней границы базового типа должны не превышать диапазона от 0 до 255. В силу этого базовый тип мно- жества не может быть коротким целым (Shortint), целым (Integer), длинным целым (Longint) или словом (Word). Примечание: Операции над множественными типами описыва- ются в разделе "Операции над множествами" в Главе 6. В раз- деле "Описатели множеств" показано, как определять значения множества. Любой множественный тип может принимать значение [], которое называется пустым множеством. Файловые типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Файловый тип состоит из линейной последовательности компо- нентов, которые могут иметь любой тип за исключением файлового типа или структурного типа, содержащего компонент с файловым ти- пом. Число компонентов описанием файлового типа не устанавливает- ся. ЪДДДДДДї ЪДДДДї ЪДДДДДї файловый тип ДДД>і file ГДДВД>і of ГДДД>і тип ГДДДДД> АДДДДДДЩ і АДДДДЩ АДДДДДЩ ^ АДДДДДДДДДДДДДДДДДДДДДЩ Если слово of и тип компонента опущены, то тип обозначает нетипизированный файл. Нетипизированные файлы представляют собой каналы ввода-вывода нижнего уровня, в основном используемые для прямого доступа к любому файлу на диске, независимо от его внут- реннего формата. Стандартный файловый тип Text определяет файл, содержащий символы, упорядоченные в строки. Текстовые файлы используют спе- циальные процедуры ввода-вывода, которые описываются в Главе 14 "Ввод и вывод". Ссылочные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Cсылочный тип (указатель) определяет множество значений, ко- торые указывают на динамические переменные определенного типа, называемого базовым типом. Переменная ссылочного типа содержит адрес динамической переменной в памяти. ЪДДДї ЪДДДДДДДДДДДДДї ссылочный тип ДДДДДД>і ^ ГДДД>і базовый тип ГДД> АДДДЩ АДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДДДДї базовый тип ДДДД>і идентификатор типа ГДДД> АДДДДДДДДДДДДДДДДДДДДДЩ Если базовый тип является еще не описанным идентификатором, то он должен быть описан в той же самой части описания типов, что и тип указатель. Переменной-указателю можно присвоить значение с помощью про- цедуры New, операции @ или функции Ptr. Процедура New отводит но- вую область памяти в динамически распределяемой области для дина- мических переменных и сохраняет адрес этой области в переменной указателя. Операция @ ориентирует переменную-указатель на область памяти, содержащую существующую переменную, включая и те перемен- ные, которые имеют идентификаторы. Функция Ptr ориентирует пере- менную-указатель на определенный адрес в памяти. Зарезервированное слово nil обозначает константу со значени- ем указателя, которая ни на что не указывает. Тип Pointer ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Встроенный тип Pointer обозначает нетипизированный указа- тель, то есть указатель, который не указывает ни на какой опреде- ленный тип. Переменные типа Pointer могут быть разыменованы: ука- зание символа ^ после такой переменной вызывает появление ошибки. Как и значение, обозначаемое словом nil, значения типа Pointer совместимы со всеми другими типами указателей. Примечание: В разделе "Указатели и динамические пере- менные" в Главе 5 вы можете найти синтаксис ссылки на дина- мические переменные, которые указываются с помощью указате- ля-переменной. Тип PChar ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Для представления указателя на строку с завершающим нулем в Borland Pascal имеется предопределенный тип PChar. В блоке System данный тип описывается следующим образом: type PChar = ^Char; Borland Pascal поддерживает набор расширенных правил, позво- ляющих работать со строками с завершающим нулем, используя тип PChar. Полностью эта тема обсуждается в Главе 18 "Использование строк с завершающим нулем". Процедурные типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В стандартном Паскале процедуры и функции рассматриваются только как части программы, которые можно выполнять с помощью вы- зова процедуры или функции. В Borland Pascal процедуры и функции трактуются гораздо шире: здесь допускается интерпретация процедур и функций, как объектов, которые можно присваивать переменным и передавать в качестве параметров. Такие действия можно выполнять с помощью процедурных типов. В описании процедурного типа задаются параметры, а для функ- ции - результат функции. процедурный тип і і ЪДДДДДДДДДї АВ>іprocedureГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД> і АДДДДДДДДДЩ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДї ^ ^ і АД>ісписок формальных параметровГДЩ і ЪЩ АДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ АДї і ЪДДДДДДДДї ЪДДДї ЪДДДДДДДДДїі А>іfunctionГВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД>і : Г>ірезультатГЩ АДДДДДДДДЩі ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДї^ АДДДЩ АДДДДДДДДДЩ А>ісписок формальных параметровГЩ АДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Характерно, что синтаксис записи процедурного типа в точнос- ти совпадает с записью заголовка процедуры или функции, только опускается идентификатор после ключевого слова procedure или function. Приведем некоторые примеры описаний процедурного типа: type Proc = procedure; SwapProc = procedure(var X, Y: Integer); StrProc = procedure(S: String); MathFunc = function(X: Real): Real; DeviceFunc = function(var F: text): Integer; MaxFunc = function(A, B: Real; F: MathFunc): Real; Имена параметров в описании процедурного типа играют чисто декоративную роль - на смысл описание они не влияют. Borland Pascal не позволяет описывать функции, которые возв- ращают значения процедурного типа. Результат функции должен быть строкового, вещественного, целого, символьного, булевского типа, указателем или иметь перечислимый тип, определенный пользовате- лем. Процедурные значения ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Переменной процедурного типа можно присвоить процедурное значение. Процедурные значения могут быть следующими: * значениями nil; * ссылкой на переменную процедурного типа; * идентификатором процедуры или функции. В контексте процедурных значений описание процедуры или функции можно рассматривать как специальный вид описаний конс- тант, когда значением константы является процедура или функция. Рассмотрим, например, следующее описание: var P: SwapProc; F: MathFunc; procedure Swap(var A, B: Integer); far; var Temp: Integer; begin Temp := A; A := B; B := Temp; end; function Tan(Angle: Real); far; begin Tan := Sin(Angle) / Cos(Angle); end; Переменным P и F можно присвоить значения следующим образом: P := Swap; F := Tan; а вызовы с помощью P и F можно выполнить так: P(I, J); { эквивалентно Swap(I, J) } X := F(X); { эквивалентно X := Tan(X) } Использование процедурных переменных, которым в операторе вызова процедуры или функции присваивается значение nil, приводит к ошибке. Значение nil предназначено для указания того, что про- цедурная переменная не присвоена, и, так где процедурная перемен- ная может получить значение nil, участвующие в этой процедурной переменной вызовы процедур и функций следует подвергать проверке: if @P <> nil then P(I, J); Обратите внимание на использование операции @ для указания того, что P проверяется, а не вызывается. Совместимость типов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Чтобы они считались совместимыми, процедурные типы должны иметь одно и то же число параметров, а параметры в соответствую- щих позициях должны иметь тождественные типы. При определении совместимости процедурных типов имена параметров значения не име- ют. Значение nil совместимо с любым процедурным типом. Чтобы использоваться в качестве процедурных значений, проце- дуры и функции должны описываться с директивой far и компилиро- ваться в состоянии с {$F+}. Кроме того, в качестве процедурных значений не могут указываться стандартные процедуры и функции, вложенные процедуры и функции, методы, процедуры и функции, опи- санные с ключевым словом inline или interrupt. Стандартные процедуры и функции - это подпрограммы, описан- ные в модуле Unit, например, WriteLn, ReadLn, Chr или Ord. Чтобы использовать в качестве процедурного значения стандартную проце- дуру и функцию, напишите для нее "оболочку". Например, следующая функция DSin совместима по присваиванию с описанным выше типом MathFunc: function FSin(X: Real): Real; far; begin FSin := Sin(X); end; Процедура или функция является вложенной, когда она описыва- ется внутри другой процедуры или функции. Такие вложенные проце- дуры и функции не могут использоваться в качестве процедурных значений. Тождественные и совместимые типы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Два типа могут быть тождественными, и эта тождественность (идентичность) является обязательной в некоторых контекстах. В других случаях два типа должны быть только совместимы или совмес- тимы по присваиванию. Два типа являются тождественными, если они описаны с одним идентификатором типа, или если их определения ис- пользуют один и тот же идентификатор типа. Тождественность типов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Тождественность типов требуется только для переменных факти- ческих и формальных параметров при вызове процедур и функций. Два типа, скажем T1 и T2, являются тождественными, если яв- ляется истинным одно из следующих утверждений: T1 и T2 представ- ляю собой один и тот же идентификатор типа; T1 описан как эквива- лентный типу, тождественному T2. Второе условие означает, что T1 не обязательно должен быть описан как непосредственно эквивалентный T2. Следующие описания типов: T1 = integer; T2 = T1; T3 = integer; T4 = T2; означают, что T1, T2, T3, T4 и integer являются тождественными типами. Следующие описания типов: T5 = set of integer; T6 = set of integer; не определяют T5 и T6 как тождественные, поскольку set of integer не является идентификатором типа. Две переменные, описанные в од- ном и том же описании, например: V1, V2: set of integer; имеют тождественные типы, поскольку их описания не раздельны. Описания: V1: set of integer; V2: set of integer; V3: integer; V4: integer; означают, что V3 и V4 имеют тождественный тип, а V1 и V2 - нет. Совместимость типов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Иногда, например, в выражениях и операциях сравнения, требу- ется совместимость типов. Совместимость типов, кроме того, явля- ется важной предпосылкой для совместимости по присваиванию. Совместимость типов имеет место, если выполняется по крайней мере одно из следующих условий: * Оба типа являются одинаковыми. * Оба типа являются вещественными типами. * Оба типа являются целочисленными. * Один тип является поддиапазоном другого. * Оба типа являются отрезками одного и того же основного ти- па. * Оба типа являются множественными типами с совместимыми ба- зовыми типами. * Один тип является строковым типом, а другой - строковым типом, упакованным строковым типом или типом PChar; * Один тип - это тип Pointer, а другой - любой ссылочный тип. * Один тип является типом PChar, а другой - символьным мас- сивом с нулевой базой вида array[0..X] of Char (это дейс- твует только при разрешении директивой {$X+} расширенного синтаксиса). * Оба типа являются указателями идентичных типов (это дейс- твует только при разрешении указателя с проверкой типа ди- рективой {$X+}). * Оба типа являются процедурными с идентичными типами ре- зультатов, одинаковым числом параметров и соответствием между параметрами. Совместимость по присваиванию ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Совместимость по присваиванию необходима, если имеет место присваивание значения, например, в операторе присваивания или при передаче значений параметров. Значение типа T1 является совместимым по присваиванию с ти- пом T2 (то есть допустим оператор T1:=T2), если выполняется одно из следующих условий: * T1 и T2 имеют тождественные типы, и ни один из них не яв- ляется файловым типом или структурным типом, содержащим компонент с файловым типом на одном из своих уровней. * T1 и T2 являются совместимыми порядковыми типами, и значе- ния типа T2 попадают в диапазон возможных значений T1. * T1 и T2 являются вещественными типами, и значения типа T2 попадают в диапазон возможных значений T1. * T1 является вещественным типом, а T2 является целочислен- ным типом. * T1 и T2 являются строковыми типами. * T1 является строковым типом, а T2 является символьным ти- пом (Char). * T1 является строковым типом, а T2 является упакованным строковым типом. * T1 и T2 являются совместимыми упакованными строковыми ти- пами. * T1 и T2 являются совместимыми множественными типами, и все члены значения типа T2 попадают в диапазон возможных зна- чений T1. * T1 и T2 являются совместимыми типами указателей. * T1 - это тип PChar, а T2 - это строковая константа (это действует только при разрешении директивой {$X+} расширен- ного синтаксиса). * T1 является типом PChar, а T2 - символьным массивом с ну- левой базой вида array[0..X] of Char (это действует только при разрешении директивой {$X+} расширенного синтаксиса). * T1 и T2 являются совместимыми процедурными типами. * T1 представляет собой процедурный тип, а T2 - процедура или функция с идентичным типом результата, идентичным чис- лом параметров и соответствием между типами параметров. * Объектный тип T2 совместим по присваиванию с объектным ти- пом T1, если T2 является доменом T1. * Тип указателя Р2, указывающий на объект типа Т3, совместим по присваиванию с типом указателя P1, указывающим на объ- ект T1, если T2 является доменом T1. На этапе компиляции и выполнения выдается сообщение об ошиб- ке, если совместимость по присваиванию необходима, а ни одно из условий предыдущего списка не выполнено. Раздел описания типов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Программы, процедуры и функции имеют для описания типов спе- циальный раздел описания типов. Например: type TRange = integer; TNumber = integer; TColor = (red,green,blue); TTextIndex = 1..100; TTestValue = -99..99; TTestList = array[TestIndex] of TestValue; PestList = ^TTestList; TDate = object year: integer; month: 1..12; day: 1.. 31; procedure SetDate(D, M, Y: Integer); function ShowDate: String; end; MeasureData = record when: Date; count: TTestIndex; data: TestListPtr; end; TMeasureList = array[1..50] of MeasureData; TName = string[80]; TSex = (male,female); TPersonDate = ^TPersonData; TPersonData = record name,firstName: TName; age: integer; married: boolean; father,child,sibling: Person; case s: Sex of male: (bearded: boolean); female: (pregnant: boolean); end; TPersonDate = array[0..SizeOf(TPersonDate)-1] of Byte; TPeople = file of TPersonData; В этом примере Range, Number и Integer являются тождествен- ными типами. TTestIndex является просто совместимым и совместимым по присваиванию, но не тождественным, с типами Number, Range и Integer. Обратите внимание на использование в описаниях TCharVal и TPersonBuf выражений-констант. Глава 5. Переменные и типизированные константы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описания переменных ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание переменной представляет собой список идентификато- ров, которые обозначают новые переменные и их типы. описание ЪДДДДДДДДДДДДї ЪДДДї ЪДДДї ЪДДДї переменной Д>ісписок иден-ГД>і : ГД>ітипГДВДДДДДДДДДДДВД>і ; Г> ітификаторов і АДДДЩ АДДДЩ і і АДДДЩ АДДДДДДДДДДДДЩ і ЪДДДДДДДДїі А>іabsoluteГЩ АДДДДДДДДЩ Тип, задаваемый для переменных, может быть идентификатором типа, который был ранее описан в разделе описания типов того же самого блока, или блока, в который входит данный блок, или моду- ля, или же этот тип может быть новым определением типа. При указании идентификатора в списке идентификаторов описа- ния переменной этот идентификатор имеет силу идентификатора пере- менной в том блоке, где это описание было указано. К этой пере- менной можно обращаться из любого места этого блока, если ее идентификатор не переопределен в блоке, входящем в первый. Пере- определение означает, что для новой переменной используется тот же самый идентификатор, но это использование не оказывает влияния на значение первоначальной переменной. Приведем пример раздела описания переменной: var X,Y,Z: real; I,J,K: integer; Digit: 0..9; C: Color; Done,Error: boolean; Operator: (plus, minus, times); Hue1,Hue2: set of Color; Today: Date; Results: MeasureList; P1,P2: Person; Matrix: array[1..10,1..10] of Real; Переменные, описанные вне процедуры и функции, называются глобальными переменными и располагаются в сегменте данных. Пере- менные, описанные в самой процедуре или функции, называются ло- кальными переменными и располагаются в сегменте стека. Глава 5. Переменные и типизированные константы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание переменной представляет собой список идентификато- ров, которые обозначают новые переменные и их типы. описание ЪДДДДДДДДДДДДї ЪДДДї ЪДДДї ЪДДДї переменной Д>ісписок иден-ГД>і : ГД>ітипГДВДДДДДДДДДДДВД>і ; Г> ітификаторов і АДДДЩ АДДДЩ і і АДДДЩ АДДДДДДДДДДДДЩ і ЪДДДДДДДДїі А>іabsoluteГЩ АДДДДДДДДЩ Тип, задаваемый для переменных, может быть идентификатором типа, который был ранее описан в разделе описания типов того же самого блока, или блока, в который входит данный блок, или моду- ля, или же этот тип может быть новым определением типа. При указании идентификатора в списке идентификаторов описа- ния переменной этот идентификатор имеет силу идентификатора пере- менной в том блоке, где это описание было указано. К этой пере- менной можно обращаться из любого места этого блока, если ее идентификатор не переопределен в блоке, входящем в первый. Пере- определение означает, что для новой переменной используется тот же самый идентификатор, но это использование не оказывает влияния на значение первоначальной переменной. Приведем пример раздела описания переменной: var X,Y,Z: real; I,J,K: integer; Digit: 0..9; C: Color; Done,Error: boolean; Operator: (plus, minus, times); Hue1,Hue2: set of Color; Today: Date; Results: MeasureList; P1,P2: Person; Matrix: array[1..10,1..10] of Real; Переменные, описанные вне процедуры и функции, называются глобальными переменными и располагаются в сегменте данных. Пере- менные, описанные в самой процедуре или функции, называются ло- кальными переменными и располагаются в сегменте стека. Сегмент данных ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Максимальный размер сегмента данных равен 65520 байт. При компоновке программы (что автоматически осуществляется в конце компиляции программы) глобальные переменные всех модулей, исполь- зуемых программой, а также собственные глобальные переменные программы, размещаются в сегменте данных. Если для глобальных переменных требуется более 65520 байт, то следует распределить большие структуры в виде динамических пе- ременных. Дальнейшее описание этой темы можно найти в разделе "Указатели и динамические переменные" настоящей главы. Сегмент стека ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Размер сегмента стека устанавливается с помощью директивы компилятора $M и лежит в пределах от 1024 до 65520 байт. По умол- чанию размер стека равен 16384 байт. При каждой активизации (вызове) процедуры или функции в стек помещается множество локальных переменных. При завершении работы память, занимаемая локальными переменными, освобождается. В любой момент выполнения программы общий размер локальных переменных в активных процедурах и функциях не должен превышать размера сег- мента стека. Примечание: Если вы пишете приложение для Windows, то Windows налагает на сегменты данных и стека специальные требования, так что рабочий максимум стека и область сег- мента данных могут быть меньше, чем упомянутые максимальные области сегмента данных и стека. Директива компилятора $S используется для проверок перепол- нения стека в программе. В состоянии {$S+}, принятом по умолча- нию, генерируется код, осуществляющий проверку переполнения стека в начале каждой процедуры или функции. В состоянии {$S-} такие проверки не проводятся. Переполнение стека может вызвать аварий- ное завершение работы системы, поэтому не следует отменять про- верки стека, если нет абсолютной уверенности в том, что перепол- нения не произойдет. Абсолютные переменные ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Переменные можно описать так, что они будут располагаться по определенному адресу в памяти, и в этом случае они называются аб- солютными переменными. Описание таких переменных должно содержать после типа оператор absolute: описание ЪДДДДДДДДї ЪДДДДДДДДДї ЪДДДї ЪДДДДДДДДДї абсолютной ДДД>іabsoluteГДВД>іцелое безГД>і : ГД>іцелое безГДВД> переменной АДДДДДДДДЩ і і знака і АДДДЩ і знака і і і АДДДДДДДДДЩ АДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і АДДДДДД>іидентификаторГДДДДДДДДДДДДЩ і переменной і АДДДДДДДДДДДДДЩ Отметим, что список идентификаторов в описании переменной при указании оператора absolute может содержать только один иден- тификатор. Первая часть оператора absolute содержит сегмент и смещение, то есть адрес, по которому переменная должна быть размещена. CrtMode : byte absolute $0040:$0049; Первая константа обозначает базу сегмента, а вторая опреде- ляет смещение внутри этого сегмента. Обе константы не должны вы- ходить за пределы диапазона от $0000 до $FFFF (от 0 до 65535). В программах защищенного режима DOS и в Windows первую форму оператор absolute нужно использовать очень аккуратно, если вообще стоит это делать. Во время выполнения прикладной программы Windows или DOS защищенного режима она может не иметь полномочий доступа к областям памяти вне вашей программы. Попытка доступа к этим областям памяти может привести к сбою программы. Вторая форма оператора absolute используется для описания переменной, которая помещается "поверх" другой переменной, то есть по тому же самому адресу, что и другая переменная. var Str: string[32]; StrLen: byte absolute Str; Это описание указывает, что переменная StrLen должна разме- щаться с того же адреса, что и переменная Str, а поскольку первый байт строковой переменной содержит динамическую длину строки, то StrLen будет содержать длину Str. Эту вторую форму оператора absolute можно без опасения ис- пользовать при программировании в Windows или в защищенном режиме DOS. Память, к которой вы обращаетесь, находится в области прог- раммы. Ссылки на переменные ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Ссылка на переменную может обозначать следующее: - переменную; - компонент в переменной структурного или строкового типа; - динамическую переменную, на которую указывает переменная типa указатель. Синтаксис ссылки на переменную имеет вид: ЪДДДДДДДДДДДДДї ссылка на ДВДД>іидентификаторГДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДД> переменную і і переменной і ^^ ЪДДДДДДДДДДДДї і і АДДДДДДДДДДДДДЩ іАДДґквалификаторі<ДЩ і ЪДДДДДДДДДДДДДДДї і АДДДДДДДДДДДДЩ ГДД>іприведение типаГДДДДДДґ і і переменной і і і АДДДДДДДДДДДДДДДЩ АДДДДДї і ЪДДДДДДДДДї ЪДДДДДДДДДДДДї і АДД>івыражениеГД>іквалификаторГДДЩ АДДДДДДДДДЩ АДДДДДДДДДДДДЩ Отметим, что синтаксис ссылки на переменную допускает ис- пользование выражения, вычисляющего значение ссылочного типа. Вы- ражение должно следовать за квалификатором, разыменовывающим ссы- лочное значение (или индексирующим значением указателя, если с помощью директивы {$X+} разрешен расширенный синтаксис), что дает фактическую ссылку на переменную. Квалификаторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Обращение к функции представляет собой идентификатор пере- менной с несколькими квалификаторами или без них, которые изменя- ют значение обращения к функции. ЪДДДДДДї квалификатор ДДВДД>іиндексГДДДДДДДДДД> і АДДДДДДЩ ^ і ЪДДДДДДДДДДДДї і ГДД>і десигнатор ГДДґ і і поля і і і АДДДДДДДДДДДДЩ і і ЪДДДї і АДД>і ^ ГДДДДДДДДДДДЩ АДДДЩ Идентификатор массива без квалификатора является ссылкой на весь массив, например: Results Идентификатор массива с указанным индексом обозначает конк- ретный элемент массива, в данном случае структурную переменную: Results[Current+1] В случае, если элементом является запись, за индексом можно указать обозначение поля. В этом случае ссылка на переменную оз- начает конкретное поле конкретного элемента массива: Results[Current+1].Data Десигнатор поля в указателе-поле может сопровождаться сим- волом указателя (^) с тем, чтобы указать различие между указате- лем-полем и динамической переменной, на которую он указывает. Results[Current+1].Data^ Если переменная, на которую указывается, является массивом, то можно добавить индексы для обозначения компонентов этого мас- сива. Results[Current+1].Data^[J] Массивы, строки и индексы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Конкретный элемент массива обозначается с помощью ссылки на переменную массива, за которой указывается индекс, определяющий данный элемент. Конкретный символ в строковой переменной обозначается с по- мощью ссылки на строковую переменную, за которой указывается ин- декс, определяющий позицию символа. ЪДДДї ЪДДДДДДДДДї ЪДДДї индекс ДД>і [ ГДДДДДДД>івыражениеГДДДДВДД>і ] ГДД> АДДДЩ ^ АДДДДДДДДДЩ і АДДДЩ і ЪДДДї і АДДДДДДДґ , і<ДДДДДДДЩ АДДДЩ Индексные выражения обозначают компоненты в соответствующей размерности массива. Число выражений не должно превышать числа индексных типов в описании массива. Более того, тип каждого выра- жения должен быть совместимым по присваиванию с соответствующим индексным типом. В случае многомерного массива можно использовать несколько индексов или несколько выражений в индексе. Например: Matrix[I][J] что тождественно записи: Matrix[I,J] Строковую переменную можно проиндексировать с помощью оди- ночного индексного выражения, значение которого должно быть в ди- апазоне 0...n, где n - указанный в описании размер строки. Это дает доступ к каждому символу в строковом значении, если значение символа имеет тип Char. Первый символ строковой переменной (индекс 0) содержит дина- мическую длину строки, то есть Length(S) тождественно Ord(S[0]). Если атрибуту длины присваивается значение, то компилятор не про- веряет, является ли это значение меньшим описанного размера стро- ки. Вы можете указать индекс строки и вне ее текущей динамической длины. В этом случае считываемые символы будут случайными, а присваивания вне текущей длины не повлияют на действительное зна- чение строковой переменной. Когда с помощью директивы компилятора {$X+} разрешен расши- ренный синтаксис, значение PChar может индексироваться одиночным индексным выражением типа Word. Индексное выражение задает смеще- ние, которое нужно добавить к символу перед его разыменованием для получения ссылки на переменную типа Char. Записи и десигнаторы полей ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Конкретное поле переменной-записи обозначается с помощью ссылки на переменную-запись, после которой указывается обозначе- ние поля, специфицирующее это поле. ЪДДДї ЪДДДДДДДДДДДДДї обозначение поля ДДД>і . іДДД>іидентификаторіДДД> АДДДЩ і поля і АДДДДДДДДДДДДДЩ Приведем несколько примеров десигнаторов полей: Today.Year Results[1].Count Result[1].When.Month В операторе, входящем в оператор with, обозначению поля не должна предшествовать ссылка на переменную, содержащую запись. Десигнаторы компонентов объекта ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Формат десигнатора компонента объекта совпадает с форматом десигнатора поля записи. То есть, он состоит из экземпляра (ссыл- ки на переменную), за которым следует точка и идентификатор ком- понента. Десигнатор компонента, который обозначает метод, называ- ется десигнатором метода. К экземпляру объектного типа можно применить оператор with. В этом случае при ссылке на компоненты объектного типа экземпляр и точку можно опустить. Экземпляр и точку можно опустить также в любом блоке метода. При этом эффект будет тот же, что и при записи перед ссылкой на компонент Self и точки. Переменные-указатели и динамические переменные ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Значением переменной-указателя является или nil (то есть пустое значение), или адрес значения, указывающий на динамическую переменную. Ссылка на динамическую переменную, на которую указывает пе- ременная-указатель, записывается в виде переменной-указателя, после которой ставится символ указателя (^). Динамические переменные и значения их указателей создаются с помощью стандартных процедур New и GetMem. Вы можете использовать операцию @ и стандартную функцию Ptr для создания значений указа- теля, которые рассматриваются как указатели динамических перемен- ных. Значение nil не указывает ни на какую переменную. Если вы попытаетесь получить доступ к динамической переменной при неопре- деленном значении указателя или указателе, равном nil, результат будет неопределенным. Приведем несколько примеров ссылок (указателей) на динами- ческие переменные: P1^ P1.Sibling^ Results[1].Data^ Приведение типов переменных ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Ссылка на переменную одного типа может быть преобразована в ссылку на переменную другого типа с помощью приведения типов пе- ременных. ЪДДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДї ЪДДДї приведение ДДД>іидентификаторГДД>і ( ГДД>іссылка на ГДД>і ) ГД> типов і типа і АДДДЩ іпеременнуюі АДДДЩ АДДДДДДДДДДДДДЩ АДДДДДДДДДДЩ Когда приведение типов применяется к ссылке на переменную, ссылка на переменную рассматривается как экземпляр типа, предс- тавленного идентификатором типа. Размер переменной (число байт, занимаемых переменной) должен быть равен размеру типа, представ- ленного идентификатором типа. После приведения типа переменной можно указать один или несколько квалификаторов, если это допус- кается указанным типом. Примечание: Определять допустимость приведения типа должен программист. Приведем несколько примеров приведения типов переменных: type TByteRec = record lo, hi: byte; end; TWordRec = record low, high: word; end; TPtrRec = record ofs, seg: word; end; PByte = ^Byte; var B: byte; W: word; L: longint; P: pointer; begin W := $1234; B := TByteRec(W).lo; TByteRec(W).hi := 0; L := $1234567; W := TWordRec(L).lo; B := PByte(L)^; P := Ptr($40,$49); W := TPtrRec(P).seg; Inc(TPtrRec(P).Ofs,4); end. Обратите внимание на использование для доступа к младшим и старшим байтам слова типа TByteRec: это соответствует встроенным функциям Lo и Hi, только над левой частью в операции присваивание может выполняться приведение типа. Отметим также, что для доступа к младшим и старшим словам длинного целого, а также к смещению и адресу сегмента указателя используются типы TWordRec и TPtrRec. Borland Pascal также полностью поддерживает приведение типов для процедурных типов. Например, имея следующие описания: type Func = function(X: Integer): Integer; var F: Func; P: Pointer; N: Integer; вы можете построить следующие присваивания: F := Func(P); { присвоить F значение процедурного типа в P } Func(P) := F; { присвоить P значение процедурного типа в F } @F := P; { присвоить F значение-указатель в P } P := @F; { присвоить P значение-указатель в F } N := F(N); { вызвать функцию через F } N := Func(P)(N); { вызвать функцию через P } Обратите в частности внимание на операцию получения адреса @, которая применяется к переменной процедурного типа. Ее можно использовать в левой части присваивания. Кроме того, отметьте приведение типа на последней строке при вызове функцию через пе- ременную-указатель. Типизированные константы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Типизированные константы можно сравнить с инициализированны- ми переменными - переменными, значения которых определяются на входе в их блок. В отличие от нетипизированных констант в описа- нии типизированной константы указывается как тип, так и значение константы. описание типизированной константы і ЪДДДДДДДДДДДДДї ЪДДДї ЪДДДї ЪДДДї ЪДДДДДДДДДДДДДДї АД>іидентификаторГД>і : ГД>ітипГД>і = ГД>ітипизированнаяГДД> АДДДДДДДДДДДДДЩ АДДДЩ АДДДЩ АДДДЩ і константа і АДДДДДДДДДДДДДДЩ типизированная ЪДДДДДДДДДДДДДДДДДДДї константа ДДДДДДВДДД>і константа ГДДДДДДД> і АДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДї і ГДДД>і адресная константаГДДДґ і АДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДї і ГДДД>і константа-массив ГДДДґ і АДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДї і ГДДД>і константа-запись ГДДДДґ і АДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДї і ГДДД>і константа-объект ГДДДґ і АДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДї і АДДД>іконстанта-множествоГДДДЩ АДДДДДДДДДДДДДДДДДДДЩ Типизированные константы можно использовать точно так же, как переменные того же самого типа, и они указываются в левой части оператора присваивания. Отметим, что типизированные конс- танты инициализируются только один раз - в начале выполнения программы. Таким образом, при каждом новом входе в процедуру или функцию локально описанные типизированные константы заново не инициализируются. Кроме обычных выражений-констант значение типизированной константы может задаваться с помощью адресного выражения-констан- ты. Адресное выражение-константа - это выражение, предусматриваю- щее получение адреса, смещения или сегмента глобальной перемен- ной, типизированной константы, процедуры или функции. Адресные выражения-константы не могут ссылаться на локальные переменные (расположенные в стеке) или динамические переменные (размещенные в динамически распределяемой области памяти), поскольку их адреса нельзя вычислить на этапе компиляции. Константы простого типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание типизированной константы с простым типом означает указание значения константы: const Maximum : integer = 9999; Factor : real = -0.1; Breakchar : char = #3; Как уже упоминалось ранее, значение типизированной константы можно задать с помощью адресного выражение-константы, то есть вы- ражения, в котором используются адрес, смещение или сегмент гло- бальной переменной, типизированной константы, процедуры или функ- ции. Например: var Buffer: array[0..1023] of Byte; const BufferOfs: Word = Ofs(Buffer); BufferSeg: Word = Seg(Buffer); Поскольку типизированная константа фактически представляет собой переменную со значением константы, она не является взаимо- заменяемой для обычных констант. Например, она не может использо- ваться в описании других констант или типов. const Min : integer = 0; Max : integer = 99; type Vector = array[Min..Max] of integer; Описание Vector является недопустимым, поскольку Min и Max являются типизированными константами. Константы строкового типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание типизированной константы строкового типа содержит максимальную длину строки и ее начальное значение: const Heading : string[7] = 'Section'; NewLine : string[2] = #13#10; TrueStr : string[5] = 'Yes'; FalseStr : string[5] = 'No'; Константы структурного типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание константы структурного типа определяет значение каждого компонента структуры. Borland Pascal поддерживает описа- ния констант типа массив, запись, множество и указатель. Констан- ты файлового типа и константы типа массив или запись, содержащие компоненты файлового типа, не допускаются. Константы типа массив ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание константы типа массив содержит значения элементов, заключенные в скобки и разделенные запятыми. ЪДДДї ЪДДДДДДДДДДДДДДї ЪДДДї константа-массив ДДД>і ( ГДДДД>ітипизированнаяГДДВД>і ) ГДД> АДДДЩ ^ і константа і і АДДДЩ і АДДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДґ , і<ДДДДДДДДЩ АДДДЩ Приведем пример константы типа массив: type Status = (Active,Passive,Waiting); StatusMap = array[Status] of string[7]; const StatStr: StatusMap = ('Active','Passive','Waiting'); В этом примере определяется константа-массив StarStr, кото- рая может использоваться для преобразования значений типа Status в соответствующие им строковые представления. Элементами массива StarStr являются: StatStr[Active] = 'Active' StatStr[Passive] = 'Passive' StatStr[Waiting] = 'Waiting' Тип элемента константы-массива может быть любым, кроме фай- лового типа. Упакованные константы строкового типа (символьные массивы) могут быть определены и как одиночные символы, и как строки. Определение: const Digits:array[0..9] of char=('0','1','2','3','4','5','6','7','8','9'); можно представить в более удобном виде: const Digits: array[0..9] of char = '0123456789'; При разрешении расширенного синтаксиса (с помощью директивы компилятора {$X+}) массивы с нулевой базой могут инициализирова- ться строкой, которая короче, чем описанная длина массива, напри- мер: const FileName = array[0..79] of Char = 'TEXT.PAS'; В таких случаях оставшиеся символы устанавливаются в NULL (#0), и массив содержит строку с завершающим нулем. Примечание: Подробнее о строках с завершающим нулем рассказывается в Главе 18. При описании константы типа "многомерный массив" константы каждой размерности заключаются в отдельные скобки и разделяются запятыми. Расположенные в середине константы соответствуют самым правым размерностям. Описание: type Cube = array[0..1,0..1,0..1] of integer; const Maze: Cube = (((0,1),(2,3)),((4,5),(6,7))); задает следующие начальные значения массива Maze: Maze[0, 0, 0] = 0 Maze[0, 0, 1] = 1 Maze[0, 1, 0] = 2 Maze[0, 1, 1] = 3 Maze[1, 0, 0] = 4 Maze[1, 0, 1] = 5 Maze[1, 1, 0] = 6 Maze[1, 1, 1] = 7 Константы типа запись ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание константы типа запись содержит идентификатор и зна- чение каждого поля, заключенные в скобки и разделенные точками с запятой. константа-запись і ЪДДДї ЪДДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДДДДДї ЪДДДї АД>і ( ГДДД>іидентификаторГД>і : ГД>ітипизированнаяГДВД>і ) ГД> АДДДЩ ^ і поля і АДДДЩ і константа і і АДДДЩ і АДДДДДДДДДДДДДЩ АДДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДДДДДДДДДДДДДДґ ; і<ДДДДДДДДДДДДДДДДДДЩ АДДДЩ Приведем несколько примеров констант-записей: type Point = record x,y: real; end; Vector = array[0..1] of Point; Month = (Jan,Feb,Mar,Apr,May,Jun,Jly,Aug,Sep,Oct,Nov,Dec); Date = record d: 1..31; m: Month; y: 1900..1999; end; const Origin : Point = (x: 0.0; y: 0.0); Line : Vector = ((x: -3.1; y: 1.5),(x: 5.8; y: 3.0)); SomeDay : Date = (d: 2; m: Dec; y: 1960); Поля должны указываться в том же порядке, как они следуют в описании типа запись. Если запись содержит поля файлового типа, то для этого типа запись нельзя описать константу. Если запись содержит вариант, то можно указывать только поля выбранного вари- анта. Если вариант содержит поле признака, то его значение должно быть определено. Константы объектного типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД При описании константы объектного типа используется тот же синтаксис, что и при описании константы типа запись. Значения для элементов (компонентов) метода задаваться не могут. С учетом при- водимых ранее описаний объектных типов, приведем некоторые приме- ры констант объектного типа: const ZeroPoint: Point = (X: 0; Y: 0) ScreenRect: Rect = (A: (X: 0; Y: 0); B: (X: 80; Y: 25); CountField: NumField = (X: 5; Y: 20; Len: 4; Name: nil; Value: 0; Min: -999; Max: 999); Константы объектного типа, которые содержат виртуальные ме- тоды, не требуется инициализировать с помощью вызова конструкто- ра. Эта инициализация автоматически выполняется компилятором. Константы множественного типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание константы множественного типа может содержать нес- колько элементов, заключенных в квадратные скобки и разделенных запятыми. Каждый элемент такой константы представляет собой конс- танту или отрезок типа, состоящий из двух констант, разделенных двумя точками. ЪДДДї ЪДДДї константа-множество Д>і [ ГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДД>і ] Г> АДДДЩ і ЪДДДДДДДДДДДДДДДДДї ^ АДДДЩ АДДД>іконстанта-элементГДВДЩ ^ АДДДДДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДДДґ , і<ДДДДДДДДЩ АДДДЩ ЪДДДДДДДДДї константа-элемент ДДДД>іконстантаГДДВДДДДДДДДДДДДДДДДДДДДДДДДД> АДДДДДДДДДЩ і ЪДДї ЪДДДДДДДДДї ^ АД>і..ГДД>іконстантаГДДЩ АДДЩ АДДДДДДДДДЩ Приведем несколько примеров констант-множеств: type Digits = set of 0..9; Letters = set of 'A'..'Z'; const EvenDigits: Digits = [0,2,4,6,8]; Vowels : Letters = ['A','E','I','O','U','Y']; HexDigits : set of '0'..'z' = ['0'..'9','A'..'F','a'..'f']; Константы ссылочного типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание константы ссылочного типа может содержать только значение nil (пусто). Приведем несколько примеров: type TDirection = (Left, Right, Up, Down); TStringPtr = ^String; TNodePtr = ^Node; TNode = record Next: NodePtr; Symbol: StringPtr; Value: Direction; end; const S1: string[4] = 'DOWN'; S2: string[2] = 'UP'; S3: string[5] = 'RIGHT'; S4: string[4] = 'LEFT'; N1: Node = (Next: nil; Symbol: @S1; Value: Down); N2: Node = (Next: @N1; Symbol: @S2; Value: Up); N3: Node = (Next: @N2; Symbol: @S3; Value: Right); N2: Node = (Next: @N3; Symbol: @S4; Value: Left); DirectionTable: NodePtr = @N4; Если разрешен расширенный синтаксис (указана директива ком- пилятора {$X+}), типизированная константа типа PChar может иници- ализироваться строковой константой, например: const Message: PChar = 'Программа завершена'; Prompt: PChar = 'Введите значения: '; Digits: array[0..9] of PChar = ( 'Ноль', 'Один', 'Два', 'Три', 'Четыре', 'Пять', 'Шесть', 'Семь', 'Восемь', 'Девять'); Результатом будет то, что указатель теперь указывает на об- ласть памяти, содержащую копию строкового литерала с завершающим нулем. Подробности вы можете найти в Главе 18 "Строки с завершаю- щим нулем". Константы процедурного типа ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Константы процедурного типа должны определять идентификатор процедуры или функции, совместимый по присваиванию с типом конс- танты. ЪДДДДДДДДДДДДДДДДДї процедурная константа ДДДДДДВДДД>іконстанта-элементГДДДДДДДДДДД> і АДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДї і ГДДД>іконстанта-элементГДДДґ і АДДДДДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДДДД>іnilГДДДДДДДДДДДЩ АДДДЩ Приведем следующий пример: type ErrorProc = procedure(ErrorCode: Integer); procedure DefaultError(ErrorCode: Integer); far; begin WriteLn('Error ', ErrorCode, '.'); end; const ErrorHandler: ErrorProc = DefaultError; Глава 6. Выражения ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Выражения состоят из операций и операндов. Большинство опе- раций в языке Паскаль являются бинарными, то есть содержат два операнда. Остальные операции являются унарными и содержат только один операнд. В бинарных операциях используется обычное алгебраи- ческое представление, например: a+b. В унарных операциях операция всегда предшествует операнду, например: -b. В более сложных выражениях порядок, в котором выполняются операции, соответствует приоритету операций (см. Таблицу 6.1). Старшинство операций Таблица 6.1 ЪДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДї і Операция і Приоритет і Вид операции і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДґ і @, not і первый (высший) і унарная операция і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДґ і *, /, div, mod, і второй і операция умножения,і і and, shl, shr і і деления, сдвига... і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДґ і +, -, or, xor і третий і операция сложения і ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДґ і =, <>, <, >, і четвертый (низший) і операция отношения і і <=, >=, in і і і АДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДЩ Для определении старшинства операций имеется три основных правила: 1. Во-первых, операнд, находящийся между двумя операциями с различными приоритетами, связывается с операцией, имею- щей более высокий приоритет. 2. Во-вторых, операция, находящаяся между двумя операциями с равными приоритетами, связывается с той операцией, ко- торая находится слева от него. 3. В-третьих, выражение, заключенное в скобки, перед выпол- нением вычисляется, как отдельный операнд. Операции с равным приоритетом обычно выполняются слева-нап- раво, хотя иногда компилятор при генерации оптимального кода мо- жет переупорядочить операнды. Синтаксис выражений ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Правила, определяющие порядок выполнения операций, вытекают из синтаксиса выражений, которые строятся из множителей, термов и простых выражений. Множитель имеет следующий синтаксис: ЪДДДДДДДДДДДДДДДї множитель ДДДВДДДДДДДДДДДДДД>і ссылка на ГДДДДДДДДДДД> і і переменную і ^ і АДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДї і ГДДДД>іконстантаГДДДДДДДДДДДДДДДДДДДДДДґ і ібез знакаі і і АДДДДДДДДДЩ і і ЪДДДї ЪДДДДДДДДДї ЪДДДї і ГДДДД>і ( ГДДДД>івыражениеіДДД>і ) ГДДДґ і АДДДЩ АДДДДДДДДДЩ АДДДЩ і і ЪДДДї ЪДДДДДДДДДї і ГДДДД>іnotГДДДД>імножительГДДДДДДДДДДДДґ і АДДДЩ АДДДДДДДДДЩ і і ЪДДДДї ЪДДДДДДДДДї і ГДДДД>ізнакГДДД>імножительГДДДДДДДДДДДДґ і АДДДДЩ АДДДДДДДДДЩ і і ЪДДДДДДДДДї і ГДДДД>і вызов ГДДДДДДДДДДДДДДДДДДДДДДґ і і функции і і і АДДДДДДДДДЩ і і ЪДДДДДДДДДДДї і ГДДДД>іконструкторГДДДДДДДДДДДДДДДДДДДДґ і і множества і і і АДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДї і ГДДДД>і адресный ГДДДДДДДДДДДДДДДДДДДДґ і і множитель і і і АДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДї і АДДДД>і приведение ГДДДДДДДДДДДДДДДДДЩ ітипа значения і АДДДДДДДДДДДДДДЩ Вызов функции активизирует функцию и представляет собой зна- чения, возвращаемые функцией (см. далее в этой главе раздел "Вы- зовы функций"). Описатель множества представляет собой значение множественного типа (см. раздел, озаглавленный, как "Описание множеств"). Приведение типа изменяет тип значения (см. "Приведе- ние типа"). Адресный множитель вычисляет адрес переменной, процедуры, функции или метода. См. раздел "Операция @". Беззнаковая константа имеет следующий синтаксис: ЪДДДДДДДДДї константа без знака ДДДВДДДД>і число ГДДДДДДДДДДДДД> і ібез знакаі ^ і АДДДДДДДДДЩ і і ЪДДДДДДДДДДї і ГДДДД>ісимвольнаяГДДДДДДДДґ і і строка і і і АДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і ГДДДД>іидентификаторГДДДДДґ і і константы і і і АДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДД>іnilГДДДДДДДДДДДДДДДЩ АДДДЩ Некоторые примеры множителей могут включать в себя: Х { ссылка на переменную } @Х { указатель на переменную } 15 { константа без знака } (Х+Y+Z) { подвыражение } SIN(Х/2) { вызов функции } ['0..''9','А'..'Z'] { описатель множества } not Done { отрицание булевской переменной } сhar(Digit+48) { назначение типа } Термы используются в операциях умножения на множитель: ЪДДДДДДДДДї терм ДДДДДДДД>імножительГДДДВДДДДДД> ^ АДДДДДДДДДЩ і і ЪДДДї і ГДДДДДґ * і<ДДДДДДДДґ і АДДДЩ і і ЪДДДї і ГДДДДДґ / і<ДДДДДДДДґ і АДДДЩ і і ЪДДДї і ГДДДДДґdivі<ДДДДДДДДі і АДДДЩ і і ЪДДДї і ГДДДДДґmodі<ДДДДДДДДі і АДДДЩ і і ЪДДДї і ГДДДДДґandі<ДДДДДДДДі і АДДДЩ і і ЪДДДї і ГДДДДДґshlі<ДДДДДДДДі і АДДДЩ і і ЪДДДї і АДДДДДґshrі<ДДДДДДДДЩ АДДДЩ Приведем несколько примеров термов: Х * Y Z / (1 - Z) Done or Error (Х <= Y) and (Y < Z) В простых выражениях к термам применяются операции сложения и присваивания знака: ЪДДДДДДДї простое выражение ДДДДДДДД>і терм ГДДДВДДДД> ^ АДДДДДДДЩ і і ЪДДДї і ГДДДДДґ + і<ДДДДДДґ і АДДДЩ і і ЪДДДї і ГДДДДДґ - і<ДДДДДДґ і АДДДЩ і і ЪДДДї і ГДДДДДґ orі<ДДДДДДі і АДДДЩ і і ЪДДДї і АДДДДДґxorі<ДДДДДДЩ АДДДЩ Приведем несколько примеров простых выражений: Х + Y -Х Hue1 + Hue2 I * J + 1 В выражениях к простым выражениям применяются операции отно- шения. ЪДДДДДДДДДї выражение ДДДД>і простое ГДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД> івыражениеі і ^ АДДДДДДДДДЩ і ЪДДДї ЪДДДДДДДДДї і ГД>і < ГДДДДДД>і простое ГДДЩ і АДДДЩ ^ івыражениеі і ЪДДДї і АДДДДДДДДДЩ ГД>і<= ГДДґ і АДДДЩ і і ЪДДДї і ГД>і > ГДДґ і АДДДЩ і і ЪДДДї і ГД>і>= ГДДґ і АДДДЩ і і ЪДДДї і ГД>і = ГДДґ і АДДДЩ і і ЪДДДї і ГД>і<> ГДДґ і АДДДЩ і і ЪДДДї і АД>іin ГДДЩ АДДДЩ Приведем некоторые примеры выражений: Х = 1.5 Done <> Error (I < J) = (J < К) C in Huel Операции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операции подразделяются на арифметические операции, логичес- кие операции, операции со строками, операции над множествами, операции отношения и операцию @ (операция получения адреса). Арифметические операции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В следующей таблице приведены типы операндов и результаты для бинарных и унарных арифметических операций: Бинарные арифметические операции Таблица 6.2 ЪДДДДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДї і Операция і Действие і Типы операндов і Тип результата і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і + і Сложение і Целый і Целый і і і і Вещественный і Вещественный і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і - і Вычитание і Целый і Целый і і і і Вещественный і Вещественный і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і * і Умножение і Целый і Целый і і і і Вещественный і Вещественный і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і / і Деление і Целый і Вещественный і і і і Вещественный і Вещественный і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і div і Целочисленноеі і і і і деление і Целый і Целый і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і mod і Остаток і Целый і Целый і АДДДДДДДДДДДБДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДЩ Примечание: Операция + используется также, как опера- ция для работы со строками и множествами. Операции +, - и * используются также для операций над множествами. Унарные арифметические операции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Таблица 6.3 ЪДДДДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДї і Операция і Действие і Тип операнда і Тип результата і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і + і Сохранение і Целый і Целый і і і знака і Вещественный і Вещественный і ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДґ і - і Отрицание і Целый і Целый і і і знака і Вещественный і Вещественный і АДДДДДДДДДДДБДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДЩ Любая операция, включающая операнд, тип которого является подмножеством порядкового типа, обрабатывается также, как если бы он был порядкового типа. Если оба операнда в операциях +, -, *, div или моd являются операндами целого типа, то тип результата будет таким же, как об- щий тип обоих операндов. (Определение общего типа см. в разделе "Целый тип" в Главе 3). Если один или более операндов в операциях +, -, или * имеют вещественный тип, то тип результата будет вещественным, если ис- пользована директива компилятора {$N-}, или типом с повышенной точностью при использовании директивы компилятора {$N+}. Если при использовании операции сохранения знака или опера- ции отрицания знака операнд имеет целый тип, то результат будет тоже целого типа. Если операнд вещественного типа, то тип резуль- тата будет вещественным или типом с повышенной точностью (extended). Значение выражения х/у всегда будет вещественного типа (real) или с повышенной точностью (extended), независимо от типов операндов. Если у равно 0, то результат будет ошибочным. Значение выражение i div j представляет собой математическое частное от i/j, округленное в меньшую сторону до значения целого типа. Если j равно 0, результат будет ошибочным. Операция mod возвращает остаток, полученный путем деления двух ее операндов, то есть: i mod j = i - (i div j) * j Знак результата операции mod будет тем же, что и знак i. Ес- ли j равно нулю, то результатом будет ошибка. Логические операции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Типы логических операций показаны в Таблице 6.4. Логические операции Таблица 6.4 ЪДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДї і Операция і Действие іТипы операндові Тип результатаі ГДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і not і Отрицание (битовое) і Целый і Целый і і and і И (битовое) і Целый і Целый і і or і ИЛИ (битовое) і Целый і Целый і і xor і Исключающее ИЛИ і Целый і Целый і і і (битовое) і і і і shl і Сдвиг влево і Целый і Целый і і shr і Сдвиг вправо і Целый і Целый і АДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДЩ Примечание: Операция not является унарной операцией. Если операндом операции not является операнд целого типа, то результат будет также целого типа. Если оба операнда в операциях or, and или xor целого типа, то тип результата будет таким же, как тип обоих операндов. Операции i shl j и i shr j сдвигают значение i влево или вправо на j битов. Тип результата будет таким же, как тип i. Булевские операции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Типы операндов и результат для булевских операций показаны в Таблице 6.5. Таблица 6.5 Булевские операции ЪДДДДДДДДДДВДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДї і Операция і Действие і Типы операндов і Тип результатаі ГДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і not і Отрицание і Булевский і Булевский і і and і Логическое И і Булевский і Булевский і і or і Логическое ИЛИ і Булевский і Булевский і і xor і Логическое і і і і і исключающее ИЛИ і Булевский і Булевский і АДДДДДДДДДДБДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДЩ Примечание: Операция not является унарной операцией. Результаты этих операций соответствуют обычной булевой логи- ке. Например, выражение a and b является истинным (принимает зна- чение Тruе) только в том случае, если оба операнда a и b имеют истинное значение (Тruе). В Borland Pascal поддерживаются две различные модели генера- ции кода для операций or и and - полное вычисление и вычисление по короткой схеме (частичное вычисление). При полном вычислении подразумевается, что каждый операнд булевского выражения, построенный с помощью операций or и and, всегда будет вычисляться, даже если результат всего выражения уже известен. Эта модель полезна в том случае, когда один или более операндов в выражении представляют собой функции с побочными эф- фектами, которые изменяют смысл программы. Вычисление по короткой схеме обеспечивает строгое вычисление слева направо. Это вычисление прекращается, как только результат всего выражения становится очевиден. Во многих случаях эта модель удобна, поскольку она обеспечивает минимальное время выполнения и, как правило, минимальный объем кода. Вычисление по короткой схеме делает также возможными такие конструкции, которые в про- тивном случае были бы недопустимы, например: while (I<=Lenght(S)) and (S[I]<>' ') do Inc(I); while (P<>nil) and (P^.Value<>5) do P:=P^.Next; В обоих случаях, если результатом первого вычисления будет значение False, вычисление второго выражения не выполняется. Схему вычисления можно задавать с помощью директивы компиля- тора $B. Значением по умолчанию является состояние {$B-} (пока оно не будет изменено с помощью "меню" возможностей компилятора). В этом случае генерируется код с вычислением по короткой схеме. В случае директивы {$B+} генерируется код с полным вычислением. Поскольку в стандартном Паскале не определяется, какую схему следует использовать для вычисления булевских выражений, то прог- раммы, зависящие от действия какой-либо конкретной схемы, в дейс- твительности не являются переносимыми. Однако, если пожертвовать переносимостью, то очень часто можно получить значительный выиг- рыш во времени выполнения и простоте, которую позволяет получить вычисление по короткой схеме. Операция со строками ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Типы операндов и результаты для операции со строками показа- ны в Таблице 6.6. Операции со строками Таблица 6.6 ЪДДДДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДї і Операция і Действие і Типы операндов іТип результатаі ГДДДДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДґ і + і Конкатенация і Строковый, і Строковый і і і і символьный или і і і і іупакованный строковыйі і АДДДДДДДДДДДБДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДЩ Borland Pascal позволяет использовать операцию + для объеди- нения двух строковых операндов. Результатом операции s + t, где s и t имеют строковый тип, символьный тип (Char) или упакованный строковый тип, будет конкатенация s и t. Результат будет совмес- тим с любым строковым типом (но не с символьным Char и не с упа- кованным строковым типом). Если длина результирующей строки пре- вышает 255 символов, то она усекается до 255 символов. Операции над символьными указателями ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Расширенный синтаксис (разрешенный по директиве компилятора {$X+}) поддерживает несколько операций с указателями на PChar. Для увеличения и уменьшения смещения указателя можно использовать операции + и -. Минус можно также использовать для вычисления расстояния (разности) между двумя символьными указателями. Если P и Q - это значения типа PChar, а I - значение типа Word, то до- пустимы следующие конструкции: Допустимые конструкции PChar Таблица 6.7 ЪДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і Операция і Результат і ГДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ і P + I і Сложение I со смещением P. і і I + P і Сложение I со смещением P. і і P - I і Вычитание I из смещения P. і і P - Q і Вычитает смещение Q из смещения P. і АДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Операции P + I и I + P складывает I c адресом, заданным P, создавая указатель, ссылающийся на I символов после P. Операция P - I вычитает I из адреса, заданного P, создавая указатель, ссыла- ющийся на I символов перед P. Операция P - Q вычитает расстояние между Q (младший адрес) и P (старший адрес), создавая в результате значение типа Word, по- казывающее число символов между Q и P. Эта операция подразумева- ет, что P и Q ссылаются на один символьный массив. Если два сим- вольный указателя ссылаются на разные массивы, то результат будет не определен. Операции над множествами ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Типы операндов для операций над множествами показаны в Таб- лице 6.7. Операции над множествами Таблица 6.7 ЪДДДДДДДДДДДДДДДВДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і Операция і Действие і Типы операндов і ГДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ і + і Объединение і Множества с совместимыми типами і і - і Разность і Множества с совместимыми типами і і * і Пересечение і Множества с совместимыми типами і АДДДДДДДДДДДДДДДБДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Результаты операций соответствуют правилам логики работы с множествами: 1. Порядковое значение c содержится в a+b только тогда, когда оно содержится в a или в b. 2. Порядковое значение c содержится в a-b только тогда, когда оно содержится в a и не содержится в b. 3. Порядковое значение c содержится в a*b только тогда, когда он содержится в обоих множествах a и b. Если наименьшим порядковым значением, которое является чле- ном результата операций над множествами, является a, а наибольшим - b, то типом результата будет множество a..b. Операции отношения ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Типы операндов и результаты операций отношения приведены в Таблице 6.8. Таблица 6.8 Операции отношения ЪДДДДДДДДДВДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДї і Операцияі Действие і Типы операндов і Тип результатаі ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і = і Равно і Совместимый простой, і Булевский і і і і указатель, множествен- і і і і і ный строковый или упа- і і і і і кованный строковый і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і <> і Не равно і Совместимый простой, і Булевский і і і і указатель, множествен- і і і і і ный, строковый или упа-і і і і і кованный строковый і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і < і Меньше чем і Совместимый простой, і Булевский і і і і указатель, множествен- і і і і і ный, строковый или упа-і і і і і кованный строковый і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і > і Больше чем і Совместимый простой, і Булевский і і і і указатель, множествен- і і і і і ный строковый или упа- і і і і і кованный строковый і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і <= і Меньше і Совместимый простой, і Булевский і і і или равно і указатель, множествен- і і і і і ный строковый или упа- і і і і і кованный строковый і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і >= і Больше і Совместимый простой, і Булевский і і і или равно і указатель, множествен- і і і і і ный строковый или упа- і і і і і кованный строковый і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і <= іПодмножествоі Множества совместимых і Булевский і і і і типов і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і >= іНадмножествоі Множества совместимых і Булевский і і і і типов і і ГДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДґ і in і Элемент і Левый операнд: любой і Булевский і і і множества і перечислимый тип t; і і і і і правый: множество, і і і і і совместимое с t. і і АДДДДДДДДДБДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДЩ Сравнение простых типов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Когда операции =, <>, <, >, >= или <= применяются для опе- рандов простых типов, то это должны быть совместимые типы. Одна- ко, если один операнд имеет вещественный тип, то другой может быть целого типа. Сравнение строк ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операции отношения =, <>, <, >, >= или <= могут применятся для сравнения строк согласно порядку расширенного набора символов кода ASСII. Любые два значения строковых данных можно сравнить, поскольку все значения строковых данных совместимы. Значения символьного типа совместимы со значениями строково- го типа, и при их сравнении символьное значение обрабатывается как строковое значение с длиной 1. Когда со значением строкового типа сравнивается упакованное строковое значение из N элементов, то оно обрабатывается, как значение строкового типа длиной N. Сравнение упакованных строк ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операции отношения =, <>, <, >, >= или <= могут применятся также для двух упакованных значений строкового типа, если они со- держат одинаковое число элементов. Если число элементов равно n, то операция соответствует сравнению двух строк, каждая из которых имеет длину n. Сравнение указателей ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операции = и <> могут использоваться для сравнения операндов типа указатель. Два указателя равны только в том случае, если они ссылаются на один и тот же объект. Сравнение символьных указателей ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД При разрешении по директиве компилятора {$X+} расширенного синтаксиса операции =, <>, <, >, >= или <= могут применятся к значениям PChar. Заметим, однако, что эти операции отношения предполагают, что два сравниваемые указателя ссылаются на один и тот же символьный массив.. По этой причине в сравнении участвуют только смещения двух значений-указателей. Если указатели ссылают- ся на разные символьные массивы, результат будет не определен. Сравнение множеств ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Если операндами являются множества a и b, то при их сравне- нии получаются следующие результаты: 1. Выражение a=b истинно (= True) только когда a и b содер- жат одни и те же элементы, в противном случае a<>b. 2. Выражение a = b истинно, когда каждый элемент множества а является также элементом множества b. 3. Выражение a = b истинно, когда каждый элемент множества b является также элементом множества a. Проверка на принадлежность к множеству ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операция in возвращает истинное значение (True), когда зна- чение элемента порядкового типа является элементом операнда мно- жественного типа, в противном случае он возвращает значение False. Операция @ ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операция @ используется в адресном коэффициенте для вычисле- ния адреса переменной, процедуры, функции или метода. В Таблице 6.9 показан операнд и типы результата. адресный коэффициент і ЪДДДї ЪДДДДДДДДДДДДДДДДДДДДДДї АДДі @ ГДДВДДДДДі ссылка не переменную ГДДДДДДДДДДДДДДДДДДДДДДД> АДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і идентификатор процедуры ГДДДДДДДДДДДґ і АДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і идентификатор функции ГДДДДДДДДДДДДДґ і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і АДДДД>і уточненный идентификатор метода ГДДДЩ АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Операция создания указателя Таблица 6.9 ЪДДДДДДДДДДДДВДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДї і Операция і Действие і Типы операндов іТип результатаі ГДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДґ і @ і Получение і Ссылка на переменную, і Указатель і і і указателя і процедуру или иденти- і (совмести- і і і і фикатор функции. і мый с nil) і АДДДДДДДДДДДДБДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДЩ Операция @ возвращает адрес операнда, то есть строит значе- ние-указатель, ссылающееся на этот операнд. Использование операции @ для переменной ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Использование операции @ для обычной переменной (не парамет- ра) не вызывает никаких сложностей. Применение @ к ссылке на пе- ременную возвращает указатель на переменную. Введем описания: type TwoChar = array[0..1] of char; var Int: integer; TwoCharPtr: ^TwoChar; тогда оператор: TwoCharPtr := @Int; приводит к тому, что TwoCharPtr для получения ссылки на TwoCharPtr^ становится повторной интерпретацией значения Int, как если бы оно было символьным массивом array[0..1]. Тип получаемого в результате указатель управляется директи- вой компилятора $T: в состоянии {$T-} (по умолчанию) типом ре- зультата будет Pointer. Другими словами, результат ом является нетипизированный указатель, совместимый со всеми другими типами указателей. В состоянии {$T+} типом результата будет ^T, где T - тип ссылки на переменную. То есть тип результата будет совместим со всеми другими указателями на тип этой переменной. Примечание: К использованию операции @ с процедурным типом применяются специальные правила. См. ниже раздел "Процедурный типы в выражениях". Использование операции @ для процедуры или функции или метода ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Вы можете применять операцию @ к процедуре, функции или ме- тоду. При этом вы получите указатель на точку входа подпрограммы. Независимо от состояния $T, типом полученного в результате указа- теля всегда будет Pointer. Другими словами, результатом всегда является нетипизированный указатель, совместимый со всеми другими ссылочными типами. При применении операции @ к методу метод должен задаваться с помощью уточненного идентификатора (идентификатора объектного ти- па, за которым следует точка и идентификатор метода). Вызовы функции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Вызовы функции приводят к активизации функции, заданной с помощью идентификатора функции. Идентификатором функции является любой идентификатор, использованный для обозначения функции. Если в соответствующем описании функции содержится список формальных параметров то в вызове функции должен содержаться спи- сок фактических параметров. Каждый параметр подставляется вместо соответствующего формального параметра в соответствии с набором правил, который вводится в Главе 9 ("Процедуры и функции"). Примечание: См. выше разделы "Активизация методов", "Активизация уточненных методов" и "Процедурные типы". ЪДДДДДДДДДДДДДї вызов функции ДВД>іидентификаторГДВВДДДДДДДДДДДДДДДДДДДДДДДДДДД> і і функции і іі ^ і АДДДДДДДДДДДДДЩ іі ЪДДДДДДДДДДДДДДДДДДї і і ЪДДДДДДДДДДДДДї іАДД>ісписок фактическихГДДЩ ГД>і десигнатор ГДґ і параметров і і і метода і і АДДДДДДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і і і уточненный і і ГД>і десигнатор ГДґ і і метода і і і АДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і АД>і ссылка на ГДЩ і переменную і АДДДДДДДДДДДДДЩ ЪДДДї ЪДДДДДДДДДДДї ЪДДДї список фактических ДДДД>і ( ГДДДДД>іфактическийГДДВД>і ) ГДДД> параметров АДДДЩ ^ і параметр і і АДДДЩ і АДДДДДДДДДДДЩ і і ЪДДДї і АДДДґ , і<ДДДДДДДДЩ АДДДЩ ЪДДДДДДДДДДДДї фактический параметр ДДВДД>і выражение ГДДДДДДДД> і АДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДї і АДД>і ссылка на ГДДДЩ і переменную і АДДДДДДДДДДДДЩ Приведем некоторые примеры вызовов функций: Sum(A,63) Maximum(147,J) Sin(X+Y) Eof(F) Volume(Radius, Height) В режиме расширенного синтаксиса ($X+) вызовы функций можно использовать в качестве операторов, то есть результат вызова функции может отбрасываться. Описатели множества ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описатель множества определяет значения множественного типа и получается путем записи выражений, заключенных в квадратные скобки ([]). Каждое выражение определяет значение множества. ЪДДДї ЪДДДї описатель ДДД>і [ ГДДВДДДДДДДДДДДДДДДДДДДДДДДД>і ] ГДДД> множества АДДДЩ і ЪДДДДДДДДДДДДї ^ АДДДЩ АДДД>і группа ГДДВДЩ ^ і элементов і і і АДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДґ , і<ДДДДДДДДЩ АДДДЩ ЪДДДДДДДДДДДї группа элементов ДД>і выражение ГДДВДДДДДДДДДДДДДДДДДДДДДДДДДДД> АДДДДДДДДДДДЩ і ^ і ЪДДї ЪДДДДДДДДДДДї і АД>і..ГДД>і выражение ГДЩ АДДЩ АДДДДДДДДДДДЩ Обозначение [ ] означает пустое множество, тип которого сов- местим по присваиванию с типом любого множества. Любая группа элементов, описанная, как х..у, объявляет элементами множества все значения в диапазоне х..у. Если х больше, чем у, то х..у не описывает никаких элементов и [x..y] обозначает пустое множество. В конкретном описателе множества все значения выражения в группах элементов должны быть одного порядкового типа. Приведем некоторые примеры описателей множеств: [red, C, green] [1,5,10..K mod 12, 13, 23] ['A'..'Z', 'a'..'z', Chr(Digit+48)] Приведение типа значений ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Тип выражения можно изменить на другой тип с помощью приве- дения типа значений. ЪДДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДї ЪДДДї приведение ДДД>іидентификаторГДД>і ( ГДД>івыражениеГДД>і ) ГД> типа значения і типа і АДДДЩ АДДДДДДДДДЩ АДДДЩ АДДДДДДДДДДДДДЩ Тип выражения и задаваемый тип должны оба иметь перечислимый тип или тип указателей. Для перечислимых типов результирующее значение получается путем преобразования выражения (и возможной проверки на нахождение в допустимых границах). Преобразование мо- жет привести к усечению или увеличению размера исходного значения в том случае, если вновь определяемый тип отличается от типа вы- ражения. В том случае, когда значение расширяется, его знак всег- да сохраняется. Таким образом, значение является расширяемым по знаку. Синтаксис приведения типа значений почти совпадает с синтак- сисом приведения типа переменных (см. раздел "Приведение типа пе- ременных" в Главе 5). Однако при приведении типа значений опера- ции производятся со значениями, а не с переменными и, таким образом, могут не участвовать в ссылках на переменные. То есть за приведением типа значения не обязательно следуют квалификаторы. В частности, приведение типа значений не должно встречаться в левой части оператора присваивания. Некоторые примеры приведения типа значений включают в себя: Intereg('A') Char(48) Boolean(0) Color(2) IntPtr(@Buffer) BytePtr(Ptr($40,$49)) Процедурные типы в выражениях ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В общем случае использование процедурной переменной в опера- торе или выражении означает вызов процедуры или функции, храня- щейся в этой переменной. Однако, имеется исключение. Когда компи- лятор видит, что процедурная переменная находится в левой части оператора присваивания, он знает, что правая часть должна предс- тавлять собой процедурное значение. Рассмотрим в качестве примера следующую программу: type IntFunc = function: Integer; var F: IntFunc; N: Integer; function ReadInt: Integer; far; var I: Integer; begin Read(I); ReadInt := I; end; begin F := ReadInt; { присваивание процедурного значения } N := ReadInt; { присваивание результата функции } end. Первый оператор основной программы присваивает процедурное значение (адрес процедуры) ReadInt процедурной переменной F, вто- рой оператор вызывает ReadInt и присваивает N возвращаемое значе- ние. Различие между получением процедурного значения или вызовом функции осуществляется по типу переменной, которой присваивается значение (F или N). К сожалению, есть ситуации, когда компилятор не может опре- делить из контекста желаемое действие. Например, в следующем опе- раторе для компилятора не очевидно, что нужно сделать: сравнить процедурное значение в F с процедурным значением ReadInt, чтобы определить, что F указывает в данный момент на ReadInt, или выз- вать F и ReadInt, а затем сравнить возвращаемые значения: if F = ReadInt then WriteLn('Equal'); Однако, стандартный синтаксис Паскаля определяет, что вхож- дение в выражение идентификатора функции означает вызов этой функции, поэтому в результате предыдущего оператора будет выпол- нен вызов F и ReadInt, а затем будут сравниваться возвращаемые значения. Чтобы сравнить процедурное значение в F с процедурным значением в ReadInt, нужно использовать следующую конструкцию: if @F = @ReadInt then WriteLn('Equal'); При применении к процедурной переменной, идентификатору про- цедуры или функции операции получения адреса @, эта операция пре- дотвращает вызов компилятором процедуры и в то же время преобра- зует аргумент в указатель. Таким образом, @F преобразует F в не- типизованный указатель-переменную, которая содержит адрес ReadInt. Для определения того, что F ссылается на ReadInt можно сравнить два значения-указателя. Операция @ часто используется при присваивании процедурной переменной нетипизированного значения-указателя. Например, опре- деленная в Windows (в модуле WinProcs) функция GetProcAddress возвращает адрес экспортируемой функции в DLL как нетипизирован- ной значение-указатель. С помощью операции @ вызов GetProcAddress можно присвоить процедурной переменной: type TStrComp = function(Str1, Str2: PChar): Integer; var StrComp: TStrComp: . . . begin . . . @StrComp := GetProcAddress(KernelHandle, 'Lstrcmpi'); . . . end. Чтобы получить адрес в памяти процедурной переменной, а не адрес, в ней записанный, используйте двойную операцию @ (@@). Например, @P означает преобразование P в нетипизированный указа- тель-переменную, в @@P означает возвращение физического адреса переменной P. Глава 7. Операторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операторы описывают те алгоритмические действия, которые должны выполняться. Операторам могут предшествовать метки, кото- рые можно использовать для ссылок в операторах перехода goto. оператор ДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДД> і ЪДДДДДї ЪДДДї ^ і ЪДДДДДДДДДДДДДДДДї ^ АД>іметкаГДД>і : ГДЩ ГДД>іпростой операторГДДґ АДДДДДЩ АДДДЩ і АДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДї і АДД>і структурный ГДДЩ і оператор і АДДДДДДДДДДДДДДДДЩ Метка - это последовательность цифр в диапазоне от 0 до 9999 или идентификатор. Существует два основных вида операторов: простые операторы и структурные операторы. Простые операторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Простым оператором является такой оператор, который не со- держит в себе других операторов. ЪДДДДДДДДДДДДДДДДДДДДДї простой оператор ДДДДВДДД>іоператор присваиванияГДДДДДДД> і АДДДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДДДї і ГДДД>і оператор процедуры ГДДДґ і АДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДї і АДДД>і оператор перехода ГДДДЩ АДДДДДДДДДДДДДДДДДДДДДЩ Оператор присваивания ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор присваивания заменяет текущее значение переменной новым значением, которое определяется выражением, или определяет выражение, значение которого должно возвращаться функцией. ЪДДДДДДДДДДДї ЪДДї ЪДДДДДДДДДї оператор ДДДДДВДД>іссылка на ГДДДДДД>і:=ГДД>івыражениеГДД> присваивания і іпеременную і ^ АДДЩ АДДДДДДДДДЩ і АДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і АДД>іидентификаторГДЩ і функции і АДДДДДДДДДДДДДЩ Выражение должно быть совместимо по присваиванию с типом пе- ременной или типом значения, возвращаемого функцией в качестве результата (см. раздел "Совместимость типов" в Главе 4). Приведем некоторые примеры операторов присваивания: X := Y + Z Done := (I >= 1) and (I < 100); Huel := [blue, Succ(C)]; I := Sqr(J) - I * K; Присваивания объектного типа Правила совместимости по присваиванию объектных типов позво- ляют присваивать экземпляру объекта экземпляр любого из его до- черних типов. Такое присваивание представляет собой проекцию потомка на пространство его предка. В примере исходного кода в Главе 4 с учетом экземпляра F типа TField и экземпляра Z типа TZipField присваивание F := Z копирует только поля X, Y, Len и Name. Присваивание экземпляру объектного типа не инициализирует экземпляр. Например, в предыдущем примере присваивание F := Z оз- начает, что вызов конструктора для F можно опустить. Операторы процедуры ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор процедуры определяет активизацию процедуры, обозна- ченную с помощью идентификатора процедуры. Если соответствующее описание процедуры содержит список формальных параметров, то опе- ратор процедуры должен содержать в себе соответствующий ему спи- сок фактических параметров (параметры, список которых приводится в определении, являются формальными параметрами, а в операторе вызова процедуры они являются фактическими параметрами). При вы- зове происходит передача фактических параметров формальным пара- метрам. ЪДДДДДДДДДДДДДї оператор ДДВД>іидентификаторГДВВДДДДДДДДДДДДДДДДДДДДДДДДДД> процедуры і і процедуры і іі ЪДДДДДДДДДДДДДДДДДДї ^ і АДДДДДДДДДДДДДЩ іАД>ісписок фактическихГДЩ і ЪДДДДДДДДДДДДДї і і параметров і ГД>і десигнатор ГДґ АДДДДДДДДДДДДДДДДДДЩ і і метода і і і АДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і ГД>і уточненный ГДґ і і десигнатор і і і і метода і і і АДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДї і АД>і ссылка на ГДЩ і переменную і АДДДДДДДДДДДДДЩ Приведем некоторые примеры операторов процедур: PrintHeaing; Transpose(A,N,M); Fin(Name,Address); Операторы перехода ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор перехода goto вызывает передачу управления операто- ру, которому предшествует метка, указанная в данном операторе пе- рехода. Синтаксическая схема оператора перехода имеет следующий вид: ЪДДДДї ЪДДДДДї оператор перехода ДДД>іgotoГДДД>іметкаГДДД> АДДДДЩ АДДДДДЩ При использовании оператора перехода должны соблюдаться сле- дующие правила: 1. Метка, которая указывается в операторе перехода, должна находиться в том же блоке или модуле, что и сам оператор перехода. Другими словами, не допускаются переходы из процедуры или функции или внутрь нее. 2. Переход извне внутрь структурного оператора (то есть пе- реход на более глубокий уровень вложенности) может выз- вать непредсказуемые эффекты, хотя компилятор не выдает сообщения об ошибке. Например, вы не должны переходить в тело цикла for. Примечание: Хорошая практика программирования требует минимального использования переходов. Структурные операторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Структурные операторы строятся из других операторов, порядок выполнения которых должен быть последовательным (составные опера- торы и операторы над записями), определяемым условной передачей управления (условные операторы) или повторяющимся (операторы цик- ла). ЪДДДДДДДДДДДДДДДДДДДДДДДї структурный ДДДДВДДДД>і составной оператор ГДДДДДДД> оператор і АДДДДДДДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і условный оператор ГДДДґ і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і ГДДДД>і оператор цикла ГДДДґ і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і АДДДД>і оператор над записями ГДДДЩ АДДДДДДДДДДДДДДДДДДДДДДДЩ Составные операторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Составные операторы задают порядок выполнения операторов, являющихся их элементами. Они должны выполняться в том порядке, в котором они записаны. Составные операторы обрабатываются, как один оператор, что имеет решающее значение там, где синтаксис Паскаля допускает использование только одного оператора. Операто- ры заключаются в ограничители begin и end, и отделяются друг от друга точкой с запятой. ЪДДДДДї ЪДДДДДДДДї ЪДДДї составной ДДДД>іbeginГДДДДДД>іоператорГДДДДВДД>іendГДД> оператор АДДДДДЩ ^ АДДДДДДДДЩ і АДДДЩ і ЪДДДї і АДДДДДґ ; і<ДДДДДДЩ АДДДЩ Приведем пример составного оператора: begin Z := X; X := Y; Y := Z; end; Условные операторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Условные операторы позволяют выбрать для выполнения один из составных операторов (или не выбрать ни одного). ЪДДДДДДДДДДДДДДДї условный оператор ДДВДД>і оператор if ГДДДДДДД> і АДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДї і АДД>і оператор case ГДДДЩ АДДДДДДДДДДДДДДДЩ Оператор условия (if) ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Синтаксис оператора if можно представить следующим образом: ЪДДї ЪДДДДДДДДДї ЪДДДДї ЪДДДДДДДДї оператор if Д>іifГДД>івыражениеГДД>іthenГДД>іоператорГДДВДДї АДДЩ АДДДДДДДДДЩ АДДДДЩ АДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДї ЪДДДДДДДДї v АДД>іelseГДД>іоператорГДДДДДДДДД> АДДДДЩ АДДДДДДДДЩ В выражении должен получаться результат, имеющий стандартный булевский тип. Если результатом выражения является истинное зна- чение (True), то выполняется оператор, следующий за ключевым сло- вом then. Если результатом выражения является значение False и при- сутствует ключевое слово else, то выполнятся оператор, следующий за ключевым словом else. Если ключевое слово else отсутствует, то никакой оператор не выполняется. Синтаксическая неоднозначность, возникающая в конструкции: if e1 then e2 else e3 разрешается путем следующей интерпретации этой конструкции: if e1 then begin if e2 then s1 else s2 end Примечание: В предшествующем операторе else двоеточие не указывается. В общем случае ключевое слово else связывается с ближайшим ключевым словом if, которое еще не связано с ключевым словом else. Приведем два примера оператора if: if X < 1.5 then Z := X+Y else Z := 1.5; if P1 <> nil then P1 := P1^.father; Оператор варианта (case) ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор варианта (casе) состоит из выражения (переключате- ля) и списка операторов, каждому из которых предшествует одна или более констант (они называются константами выбора) или ключевое слово else. Переключатель (селектор) должен иметь порядковый тип (размером в байт или слово). Таким образом, строковый тип и длин- ный целый тип являются недопустимыми типами переключателя. Все константы выбора должны быть уникальными и иметь порядковый тип, совместимый с типом переключателя. ЪДДДДї ЪДДДДДДДДДї ЪДДї ЪДДДДї оператор case Д>іcaseГДД>івыражениеГДД>іofГДДДДД>іcaseГДДВДДї АДДДДЩ АДДДДДДДДДЩ АДДЩ ^ АДДДДЩ і і і ЪДДДДї і і АДДДґ ; і<ДЩ і АДДДДЩ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і ЪДДДї АДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДД>іendГДД> і ЪДДДДДДДДДДї ^ і ЪДДДї ^ АДДДЩ АДД>іветвь elseГДДЩ АД>і ; ГДДЩ АДДДДДДДДДДЩ АДДДЩ ЪДДДДДДДДДДДДДДДДДДДДї ЪДДДДДДДДДї і ЪДДї ЪДДДДДДДДДї v ЪДДДї ЪДДДДДДДДї case ДД>іконстантаГДБД>і..ГД>іконстантаГДДВД>і : ГД>іоператорГД> ^ АДДДДДДДДДЩ АДДЩ АДДДДДДДДДЩ і АДДДЩ АДДДДДДДДЩ і ЪДДДї і АДДДДДДДДДДДДДДДДДґ , і<ДДДДДДДДДДДДДЩ АДДДЩ ЪДДДДї ЪДДДДДДДДї ветвь else ДДДД>іelseГДДД>іоператорГДДД> АДДДДЩ АДДДДДДДДЩ Оператор варианта case приводит к выполнению оператора, ко- торому предшествует константа выбора, равная значению переключа- теля или диапазону выбора, в котором находится значение переклю- чателя. Если такой константы выбора или такого диапазона выбора не существует и присутствует ветвь else, то выполнятся оператор, следующий за ключевым словом else. Если же ветвь else отсутству- ет, то никакой оператор не выполняется. Приведем некоторые примеры оператора варианта: case Operator of plus: X := X+Y; minus: X := X-Y; times: X := X*Y; end; case I of 0, 2, 4, 6, 8: Writeln('Четная цифра'); 1, 3, 5, 7, 9: Writeln('Нечетная цифра'); 10..100: Writeln('Между 10 и 100'); end; Оператор цикла ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор цикла задает повторное выполнение определенных опе- раторов. ЪДДДДДДДДДДДДДДДДДї оператор цикла ДДДВДД>і оператор repeat ГДДДДДД> і АДДДДДДДДДДДДДДДДДЩ ^ і ЪДДДДДДДДДДДДДДДДДї і ГДД>і оператор while ГДДґ і АДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДї і АДД>і оператор for ГДДЩ АДДДДДДДДДДДДДДДДДЩ Если число повторений заранее известно, то подходящей конс- трукций является оператор for. В противном случае следует исполь- зовать операторы while или repeat. Для управления повторением операторов можно использовать стандартные процедуры Break и Continue. Break завершает оператор цикла, а Continue продолжает со следующей итерации этого операто- ра. Подробности вы можете найти в Главе 1 "Справочного руководс- тва программиста". Оператор цикла с постусловием (repeat) ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В операторе цикла с постусловием (начинающимся со слова repeat) выражение, которое управляет повторным выполнением после- довательности операторов содержится внутри оператора repeat. ЪДДДДДДї ЪДДДДДДДДї ЪДДДДДї ЪДДДДДДДДДї оператор Д>іrepeatГДДДД>іоператорГДДВД>іuntilГДД>івыражениеГДД> repeat АДДДДДДЩ ^ АДДДДДДДДЩ і АДДДДДЩ АДДДДДДДДДЩ і ЪДДДї і АДДДДґ ; і<ДДДДЩ АДДДЩ Результат выражения должен быть булевского типа. Операторы, заключенные между ключевыми словами repeat и until, выполняются последовательно до тех пор, пока результат выражения не примет значение True. Последовательность операторов выполнится по край- ней мере один раз, поскольку вычисление выражения производится после каждого выполнения последовательности операторов. Приведем примеры оператора цикла с постусловием: repeat K := I mod J; I := J; J := K; until J = 0; repeat Write('Введите значение (0..9):'); Readln(I); until (I >= 0) and (I <= 9); Операторы цикла с предусловием (while) ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Оператор цикла с предусловием (начинающийся с ключевого сло- ва while) содержит в себе выражение, которое управляет повторным выполнением оператора (который может быть составным оператором). ЪДДДДДї ЪДДДДДДДДДї ЪДДї ЪДДДДДДДДї оператор ДДД>іwhileГДД>івыражениеГДД>іdoГДД>іоператорГДД> while АДДДДДЩ АДДДДДДДДДЩ АДДЩ АДДДДДДДДЩ Выражение, с помощью которого осуществляется управление пов- торением оператора, должно иметь булевский тип. Вычисление его производится до того, как внутренний оператор будет выполнен. Внутренний оператор выполнятся повторно до тех пор, пока выраже- ние принимает значение Тruе. Если выражение с самого начала при- нимает значение False, то оператор, содержащийся внутри оператора цикла с предусловием, не выполняется. Примерами операторов цикла с предусловием могут служить сле- дующие операторы: while Data[I] <> X do I := I + 1; While I > 0 do begin if Odd(I) then Z := Z * X; I := I div 2; X := Sqr(X); end; while not Eof(InFile) do begin Readln(InFile,Line); Process(Line); end; Операторы цикла с параметром (for) ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Операторы цикла с параметром (которые начинаются со слова for) вызывает повторяющееся выполнение оператора (который может быть составным оператором) пока управляющей переменной присваива- ется возрастающая последовательность значений. ЪДДДї ЪДДДДДДДДДДДї ЪДДї ЪДДДДДДДДї оператор ДДД>іforГДД>іуправляющаяГДД>і:=ГДД>іисходноеГДДДї for АДДДЩ іпеременная і АДДЩ ізначениеі і АДДДДДДДДДДДЩ АДДДДДДДДЩ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і ЪДДї і ЪД>іtoГДДДДДї ЪДДДДДДДДї ЪДДї ЪДДДДДДДДї АДДДґ АДДЩ ГДД>іконечноеГДД>іdoГДД>іоператорГДДД> і ЪДДДДДДї і ізначениеі АДДЩ АДДДДДДДДЩ АД>іdowntoГДЩ АДДДДДДДДЩ АДДДДДДЩ ЪДДДДДДДДДДДДДДДДДДДДДДДДї управляющая переменная ДДД>іидентификатор переменнойГДДД> АДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДї исходное значение ДДДД>івыражениеГДДД> АДДДДДДДДДЩ ЪДДДДДДДДДї конечное значение ДДДД>івыражениеГДДД> АДДДДДДДДДЩ В качестве управляющей переменной должен использоваться идентификатор переменой (без какого-либо квалификатора), который обозначает переменную, объявленную локальной в блоке, в котором содержится оператор for. Управляющая переменная должна иметь пе- речислимый тип. Начальное и конечное значения должны иметь тип, совместимый по присваиванию с перечислимым типом. Примечание: О локальности и области действия рассказы- вается в Главе 8. Когда начинает выполняться оператор for, начальное и конеч- ное значения определяются один раз, и эти значения сохраняются на протяжении всего выполнения оператора for. Оператор, который содержится в теле оператора for, выполня- ется один раз для каждого значения в диапазоне между начальным и конечным значением. Управляющая переменная всегда инициализирует- ся начальным значением. Когда работает оператор for, значение уп- равляющей переменной (счетчика циклов) увеличивается при каждом повторении на единицу. Если начальное значение превышает конечное значение, то содержащийся в теле оператора for оператор не выпол- нятся. Когда в операторе цикла используется ключевое слово downto, значение управляющей переменной уменьшается при каждом повторении на единицу. Если начальное значение в таком операторе меньше, чем конечное значение, то содержащийся в теле оператора цикла оператор не выполнятся. Если оператор, содержащийся в теле оператора for, изменяет значение управляющей переменной, то это является ошибкой. После выполнения оператора for значение управляющей переменной стано- вится неопределенным, если только выполнение оператора for не бы- ло прервано с помощью оператора перехода. Если принять во внимание эти ограничения, то оператор for V := Expr1 to Expr2 do Body; эквивалентен оператору: begin Temp1 := Expr1; Temp2 := Expr2; if Temp1 <= Temp2 then begin V := Temp1; Body; while V <> Temp2 do begin V := Succ(V); Body; end; end; end; и оператор цикла: for V := Expr1 downto Exp2 do Body; эквивалентен операторам: begin Temp1 := Expr1; Temp2 := Expr2; if Temp1 >= Temp2 then begin V := Temp1; Body; while V <> Temp2 o begin V := Pred(V); Body; end; end; end; где Temp1 и Temp2 - вспомогательные переменные, тип которых сов- падает с основным типом переменной V и которые не встречаются в другом месте программы. Приведем примеры оператора цикла с параметром: for I := 2 to 63 do if Data[I] > Max then Max := Data[I] for I := 1 to 10 do for J := 1 to 10 do begin X := 0; for K := 1 to 10 do X := X + Mat1[I,K]*Mat2[K,J]; Mat[I,J] := X; end; for C := red to blue do Check(C); Оператор with ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В операциях над записями оператор with удобно использовать для краткого обращения к полям записи. В операторе with к полям одной или более конкретных переменных типа запись можно обращать- ся, используя только идентификаторы полей. Оперaтор with имеет следующий синтаксис: ЪДДДДї ЪДДДДДДДДДДДДДДДї ЪДДї ЪДДДДДДДДї оператор ДД>іwithГДДДДД>і ссылка на ГДДВД>іdoГДД>іоператорГ> with АДДДДЩ ^ іпеременную типаі і АДДЩ АДДДДДДДДЩ і і запись і і і і или объект і і і АДДДДДДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДДДґ , і<ДДДДДДДДЩ АДДДЩ ссылка на переменную ЪДДДДДДДДДДДДДДДДДДДДї типа запись или объект ДДД>іссылка на переменнуюГДД> АДДДДДДДДДДДДДДДДДДДДЩ Возьмем следующее описание: type TDate = record Day : Integer: Month : Integer; Year : Integer: end; var OrderDate: TDate; С учетом данного описания приведем пример оператора with: with OrderDate do if Month = 12 then begin Month := 1; Year := Year + 1 end else Month := Month + 1; Это эквивалентно следующему: if OrderDate.Month = 12 then begin OrderDate.Month := 1; OrderDate.Year := TDate.Year + 1 end else Date.month := TDate.Month + 1; В операторе with сначала производится проверка каждой ссылки на переменную, а именно: можно ли ее интерпретировать, как поле записи. Если это так, то она всегда интерпретируется именно таким образом, даже если имеется доступ к переменной с тем же именем. Допустим описаны следующие переменные: type TPoint = record x,y: Integer; end; var x: Point; y: Integer; В этом случае и к x, и к y можно обращаться, как к перемен- ной или как к полю записи. В операторе: with x do begin x := 10; y := 25; end; x между ключевыми словами with и dо относится к переменной типа указатель, а в составном операторе x и y ссылаются на x.x и y.y. Оператор: with V1,V2,...Vn do s; эквивалентен операторам: with V1 do with V2 do ... with Vn do S; В обоих случаях, если Vn является полем и v1, и v2, то она интерпретируется как v2.Vn, а не как v1.Vn. Если выборка переменной типа запись связана с индексировани- ем массива или разыменованием указателя, то эти действия произво- дятся до того, как будет выполняться составной оператор. Глава 8. Блоки, локальность и область действия ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Блоки состоят из описаний, которые записаны и скомбинированы в любом порядке, и операторов. Каждый блок является частью описа- ния процедуры или функции, или частью программы или модуля. Все идентификаторы и метки, объявленные в разделе описаний, являются для блока локальными. Синтаксис ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В общем виде любой блок имеет следующий формат: ЪДДДДДДДДДДї ЪДДДДДДДДДДї блок ДДДД>і раздел ГДДДД>і раздел ГДДДД> і описания і іоператорові АДДДДДДДДДДЩ АДДДДДДДДДДЩ раздел ДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДД> объявления ^ і ^ і і і ЪДДДДДДДДДДДДДДДДДДї і і і ГДДД>і раздел описания ГДДДДДДґ і і і і меток і і і і і АДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДї і і і ГДДД>і раздел описания ГДДДДДДґ і і і і констант і і і і і АДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДї і і і ГДДД>і раздел описания ГДДДДДДґ і і і і типов і і і і і АДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДї і і і ГДДД>і раздел описания ГДДДДДДґ і і і і переменных і і і і і АДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДї і і і ГДДД>і оператор exports ГДДДДДДґ і і і АДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДї і і і АДДД>і раздел описания ГДДДДДДЩ і і іпроцедур и функцийі і і АДДДДДДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Раздел описания меток - это та часть блока, где описываются метки, присваиваемые операторам в соответствующем разделе опера- торов. Каждая метка должна помечать только один оператор. раздел ЪДДДДДДДї ЪДДДДДДДї ЪДДДї описания ДДДДДДД>і label ГДДДДДД>і метка ГДДВДД>і ; ГДДД> меток АДДДДДДДЩ ^ АДДДДДДДЩ і АДДДЩ і ЪДДДї і АДДДґ , ГДДДДДДЩ АДДДЩ Меткой может быть идентификатор или последовательность цифр. Используемая в качестве метки последовательность цифр должна на- ходиться в диапазоне от 0 до 9999. Раздел описания констант содержит описания констант, локаль- ных для этого блока. раздел ЪДДДДДДДї ЪДДДДДДДДДДДДї описания ДДДДД>і const ГДДДДВД>і описание ГДДДДДДДДДДДВДДД> констант АДДДДДДДЩ ^ і і константы і ^ і і і АДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДДї і і і і і описание і і і і АД>і типизированной ГДЩ і і і константы і і і АДДДДДДДДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Раздел описания типов включает описания всех типов в блоке. раздел ЪДДДДДДДї ЪДДДДДДДДДДДДї описания ДДДДД>і type ГДДДДДД>і описание ГДДДДВДДД> типов АДДДДДДДЩ ^ і типа і і і АДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДЩ Раздел описания переменных состоит из описания переменных, локальных для этого блока. раздел ЪДДДДДї ЪДДДДДДДДДДДДї описания ДДДДД>і var ГДДДДДД>і описание ГДДДДВДДД> переменных АДДДДДЩ ^ і переменной і і і АДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДЩ Раздел описания процедур и функций состоит из описания про- цедур и функций, локальных для этого блока. раздел ЪДДДДДДДДДДДДї описания ДДДДДДДДДДДВД>і описание ГДДДДДВДДДД> процедур и ^ і і процедуры і ^ і функций і і АДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДї і і і АД>і описание ГДДЩ і і і функции і і і АДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДї і ГДДДД>і описание ГДДДДДґ і іконструктораі і і АДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДї і ГДДДД>і описание ГДДДДДґ і ідеструктора і і і АДДДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДЩ В операторе exports перечисляются все процедуры и функции, которые экспортируются данной программой или динамически компону- емой библиотекой. Оператор exports допускается только во внешнем разделе описаний программы или динамически компонуемой библиотеки - в разделе описаний процедуры, функции или модуля его использо- вать нельзя. Раздел операторов определяет операторы или алгоритмические действия, которые выполняются в блоке. раздел ЪДДДДДДДДДДДї операторов ДДДДД>і составной ГДДДДД> і оператор і АДДДДДДДДДДДЩ Правила для области действия ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Наличие идентификатора или метки в описании означает опреде- ление идентификатора или метки. Каждый раз, когда идентификатор или метка встречаются в программе, они должны находиться в облас- ти действия этого описания. Область действия для блока ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Область действия идентификатора или метки в описании метки, константе, типа, переменной, процедуры или функции распространя- ется от их описания до конца текущего блока, включая все блоки, входящие в текущий блок. Ниже приводится несколько исключений. Идентификатор или метка, описанные во внешнем блоке, могут заново описываться во внутреннем блоке, входящем во внешний блок. До точки описания во внутреннем блоке или после конца вложенного блока идентификатор или метка представляют элемент, описанный во внешнем охватывающем блоке. program Outer; { начало внешней области действия ъ type I = Integer; { определяет I как Integer } var T: I; { определяет T как целочисленную переменную } procedure Inner; { начало внутреннего блока } type T = I; { переопределяет T с типом Integer } var I: T; { переопределяет I как целочисленную переменную } begin I := 1; { конец вложенного блока } end; begin T := 1; { конец внешнего блока } end. Область действия записи ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Область действия идентификатора поля, описанного в определе- нии записи, простирается от точки описания до конца определения типа запись. Кроме того, область действия идентификаторов включа- ет десигнаторы поля и операторы with над ссылками на переменную данного типа записи. Примечание: О типе запись рассказывается в Главе 4. Область действия объекта ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Область действия идентификатора элемента, описанного в объ- ектном типе, простирается от точки описания до конца определения объектного типа и распространяется на все дочерние объектные типы и блоки всех описаний методов объектного типа. Область действия идентификаторов элемента включает десигнаторы поля и операторы with над ссылками на переменную данного объектного типа. Примечание: о типе запись рассказывается в Главе 4. Область действия модуля ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Область действия идентификаторов, описанных в интерфейсной секции модуля, подчиняется правилам области действия блока и распространяется на всех клиентов модуля. Другими словами, прог- раммы и модули, содержащие операторы uses (операторы использова- ния) имеют доступ к идентификаторам, которые описаны в интерфейс- ной части модулей, указанных в этих операторах uses. Каждый модуль в операторе uses определяет свою область дейс- твия, которая охватывает остальные модули и программу в целом. Первый модуль в операторе uses представляет самую внешнюю область действия, а последний модуль представляет самую внутреннюю об- ласть действия. Это означает, что если два или более модулей со- держат описание одного и того же идентификатора, то при неуточ- ненном обращении к этому идентификатору будет выбран тот вариант, который был описан в последнем модуле в операторе uses. Однако, вы можете выбрать любой вариант этого идентификатора, указав уточненный идентификатор. Идентификаторы встроенных констант, типов, переменных, про- цедур и функций Borland Pascal действуют, как если бы они были описаны в блоке, охватывающем все используемые модули и программу в целом. В действительности эти стандартные объекты описаны в мо- дуле System, который используется любой программой или модулем прежде любого модуля, указанного в операторе uses. Это означает, что любой модуль или программа могут переопределить стандартные идентификаторы, а обращение к ним может быть выполнено с помощью уточненного (составного) идентификатора, например, System.Integer или System.Writeln. Глава 9. Процедуры и функции ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Процедуры и функции позволяют включать в основной программ- ный блок дополнительные блоки. Каждое описание процедуры или функции содержит заголовок, за которым следует программный блок. Процедура активизируется с помощью оператора процедуры. Функция активизируется при вычислении выражения, содержащего вызов функ- ции, и возвращаемое функцией значение подставляется в это выраже- ние. Примечание: Определение блока вы можете найти в Главе 8 "Блоки, локальность и область действия". В данной главе обсуждаются различные способы описания проце- дуры или функции и их параметры. Описания процедур ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание процедуры позволяет связать идентификатор с проце- дурным блоком. Процедуру можно затем активизировать с помощью оператора процедуры. ЪДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДДДї ЪДДДї описание ДДД>ізаголовокГДД>і ; ГДД>і тело ГДД>і ; ГДД> процедуры іпроцедурыі АДДДЩ іподпрограммыі АДДДЩ АДДДДДДДДДЩ АДДДДДДДДДДДДЩ ЪДДДДДДДДДї ЪДДДДДДДДДДДДДї заголовок ДД>іprocedureГДВ>іидентификаторГДДї процедуры АДДДДДДДДДЩ і АДДДДДДДДДДДДДЩ ^ГДДДДДДДДДДДДДДДДДД> і ЪДДДДДДДДДДДДДї іі ЪДДДДДДДДДДї ^ і і уточненный і іі і список і і А>іидентификаторГДЩАД>іформальныхГДЩ і метода і іпараметрові АДДДДДДДДДДДДДЩ АДДДДДДДДДДЩ ЪДДДДДДї блок ДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДД>імодульГДДДДДДДД> подпрограммыі ЪДДДДДДДДДї ЪДДДї ^ і АДДДДДДЩ ^ ГДД>і near ГДДДДД>і ; ГДДДЩ і ЪДДДДДДДї і і АДДДДДДДДДЩ ^ АДДДЩ іДД>іforwardГДДДґ і ЪДДДДДДДДДї і і АДДДДДДДЩ і ГДД>і far ГДДґ і ЪДДДДДДДДДї і і АДДДДДДДДДЩ і іДД>ідирективаГДґ і ЪДДДДДДДДДї і і і externalі і ГДД>і export ГДДґ і АДДДДДДДДДЩ і і АДДДДДДДДДЩ і і ЪДДДДДДДДї і і ЪДДДДДДДДДї і АДД>іблок asmГДДґ ГДД>іinterruptГДДЩ АДДДДДДДДЩ і і АДДДДДДДДДЩ ЪДДДДДДДДДї і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД>ідирективаГДЩ і inline і АДДДДДДДДДЩ Заголовки процедур именуют идентификаторы процедур и задают формальные параметры (если они имеются). Примечание: Синтаксис списка формальных параметров по- казан далее в этой главе в разделе "Параметры". Процедура активизируется с помощью оператора процедуры, в котором содержатся имя процедуры и необходимые параметры. Опера- торы, которые должны выполняться при запуске процедуры, содержат- ся в операторной части модуля процедуры. Если в содержащемся в процедуре операторе внутри модуля процедуры используется иденти- фикатор процедуры, то процедура будет выполняться рекурсивно (бу- дет при выполнении обращаться сама к себе). Приведем пример описания процедуры: procedure NumString(N: integer; var S: string); var V: integer; begin V := Abs(N); S := ''; repeat S := Chr(N mod 10 + Ord('0')) + S; N := N div 10; until N = 0; if N < 0 then S := '-' + S; end; Описания near и far ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Borland Pascal поддерживает две модели вызова процедур - ближнюю (near) и дальнюю (far). С точки зрения объема программы и скорости выполнения ближняя модель вызова более эффективна, но с ней связаны ограничения: процедуры типа near могут вызываться только в том модуле, где они описаны. Процедуры же с дальним ти- пом вызова можно вызывать из любого модуля, но они несколько ме- нее эффективны. Примечание: О вызовах ближнего и дальнего типа расска- зывается в Главе 22 "Вопросы управления". На основе описания процедуры компилятор будет автоматически выбирать правильную модель вызова. Для процедур, описанных в ин- терфейсной части модуля (interface), используется дальняя модель вызова - их можно вызывать из других модулей. Процедуры, описан- ные в секции реализации модуля (implementation), имеют ближний тип вызова. Вызываться они могут только из программ данного моду- ля. Для некоторых специальных целей может потребоваться исполь- зовать модель с дальним типом вызова. Например, в оверлейных за- дачах обычно требуется, чтобы все процедуры и функции имели даль- ний тип вызова. Аналогично, если процедура или функция присваивается процедурной переменной, то она также должна исполь- зовать дальний тип вызова. Чтобы переопределить автоматический выбор модели вызова компилятором, можно использовать директиву компилятора {$F+}. Процедуры и функции, компилируемые в состоянии {$F+}, всегда будут иметь дальний тип вызова (far), а в состоянии {$F-} компилятор автоматически выбирает корректную модель. По умолчанию используется директива {$F-}. Чтобы задать конкретную модель вызова, в описании процедуры перед ее блоком можно указать директиву near или far. При наличии такой директивы она переопределяет директиву $F компилятора и ав- томатический выбор модели вызова. Описания export ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание export делает процедуру или функцию экспортируемой, вынуждая компилятор использовать для нее дальний тип вызова и ге- нерировать специальный код входы и выхода из процедуры. Процедуры и функции должны быть экспортируемыми в следующих случаях: * Процедуры и функции экспортируются DLL (динамически компо- нуемой библиотекой). * Процедуры и функции системного вызова в программе Windows. О том, как экспортировать процедуры и функции в DLL, расска- зывается в Главе 11 "Динамически компонуемые библиотеки". Хотя процедура и функция компилируется с директивой export, фактичес- кий экспорт процедуры или функции не происходит, пока подпрограм- ма не перечисляется в операторе exports библиотеки. Процедуры и функции системного вызова - это те процедуры и функции вашей прикладной программы, которые вызываются самой Windows, а не вашей прикладной программой. Подпрограммы системно- го вызова должны компилироваться с директивой export, но в опера- торе exports их перечислять не нужно. Приведем некоторые примеры процедур и функций системного вызова: * процедуры Windows; * диалоговые процедуры; * процедуры системного вызова для перечисления; * процедуры уведомления об обращении к памяти; * специализированные процедуры Windows (фильтры). Borland Pascal автоматически генерирует для процедур и функ- ций, экспортируемых программой Windows, эффективные системные вы- зовы. Эффективные вызовы ослабляют необходимость использования при создании подпрограмм системного вызова подпрограмм API Windows MakeProcInstance и FreeProcInstance. Примечание: См. раздел "Код входа и выхода" в Главе 22. Описания interrupt ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В описании процедуры перед блоком операторов может указыва- ется директива interrupt. Процедура в этом случае рассматривает- ся, как процедура прерывания. Отметим пока, что процедура interrupt не может вызываться из операторов процедуры, и что каж- дая процедура interrupt должна определять список параметров, нап- ример, следующим образом: procedure MyInt(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt; Примечание: Не используйте директиву interrupt при разработке программ для Windows - это приведет к сбою. Список параметров не обязательно должен совпадать с указан- ным синтаксисом - он может быть короче и использовать другие име- на, но регистры должны передаваться в указанном порядке. Описание forward ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание процедуры, содержащее вместо блока операторов ди- рективу forward, называется опережающим описанием. В каком-либо месте после этого описания с помощью определяющего описания про- цедура должна определяться. Определяющее описание - это описание, в котором используется тот же идентификатор процедуры, но опущен список формальных параметров и в которое включен блок операторов. Описание forward и определяющее описание должны присутствовать в одной и той же части описания процедуры и функции. Между ними мо- гут описываться другие процедуры и функции, которые могут обра- щаться к процедуре с опережающим описанием. Таким образом возмож- на взаимная рекурсия. Опережающее описание и определяющее описание представляют собой полное описание процедуры. Процедура считается описанной с помощью опережающего описания. Примечание: В интерфейсной части модуля описания forward не допускаются. Приведем следующий пример опережающего описания: procedure Walter(m,n : integer); forward; procedure Clara(x,y : real); begin . . . end; procedure Walter; begin . . Clara(8.3, 2.4); . . end; Определяющее описание процедуры может быть внешним описани- ем. Однако, оно не может быть внутренним описанием или другим опережающим описанием. Определяющее описание также не может со- держать директиву interrupt, описания assembler, near, far, export, inline или другое описание forward. Описания external ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описания external позволяют связывать отдельно скомпилиро- ванные процедуры и функции, написанные на языке ассемблера. Опи- сания external позволяют также импортировать процедуры и функции из DLL. Примечание: Более детальное описания компоновки с программой на языке ассемблера содержится в Главе 25. директива external і ЪДДДДДДДДДДї АД>і external ГВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД> АДДДДДДДДДДЩі ЪДДДДДДДДДДДДДДДДДДДї ^ А>істроковая константаГВДДДДДДДДДДДДДДДДДДДДДДДЩ АДДДДДДДДДДДДДДДДДДДЩі ЪДДДДДДї ЪДДДДДДДДДї^ Г>і name ГД>істроковаяГґ і АДДДДДДЩ іконстантаіі і АДДДДДДДДДЩі і ЪДДДДДДДї ЪДДДДДДДДДїі А>і index Г>і целая ГЩ АДДДДДДДЩ іконстантаі АДДДДДДДДДЩ Директива external, состоящая только из зарезервированного слова external, используется в сочетании с директивами {$L имя_файла} для компоновки с процедурами и функциями, реализован- ными в файлах .OBJ. Приведем следующие примеры описаний внешних процедур: procedure MoveWord(var source,dest; count: longint); external; procedure MoveLong(var source,dest; count: longint); external; procedure FillWord(var dest,data: integer; count: longint); external; procedure FillLong(var dest,data: integer; count: longint); external; {$L BLOCK.OBJ} Внешними процедурами следует пользоваться, когда вы хотите объединить большое количество объектных модулей. Если ваши прог- раммы имеют небольшой объем, лучше вместо этого использовать внутренние процедуры. Директивы external, специфицирующие имя динамически компону- емой библиотеки (и, возможно, импортируемое имя или порядковый номер импорта), используются для импорта процедур и функций из динамически компонуемых библиотек. Например, следующая директива external импортирует из DLL с именем KERNEL (ядро Windows) функ- цию с именем GlobalAlloc: function GlobalAlloc(Flags: Word; Bytes: Longint): THandle; far; external 'KERNEL' index 15; В импортируемой процедуре или функции директива external за- нимает место описания и операторной части. В импортируемых проце- дурах или функциях должен использоваться дальний тип вызова, за- даваемый с помощью директивы far в описании процедуры или дирек- тивы компилятора {$F+}. В остальном импортируемые процедуры и функции аналогичны обычным процедурам и функциям. Примечание: Подробнее об импорте функций из DLL расс- казывается в Главе 11. Описания assembler ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описания assembler позволяют вам написать всю процедуру или функцию на ассемблере. Примечание: Более подробно о процедурах и функциях на Ассемблере рассказывается в Главе 24 "Встроенный ассемблер". ЪДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДї ЪДДДДДДДДДДДДї блок asm Д>іassemblerГДД>і ; ГДД>і раздел ГДД>іasm операторГД> АДДДДДДДДДЩ АДДДЩ і описания і АДДДДДДДДДДДДЩ АДДДДДДДДДДЩ Описания inline ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Директивы inline позволяют записывать вместо блока операто- ров инструкции в машинном коде. При вызове обычной процедуры ком- пилятор создает код, в котором параметры процедуры помещаются в стек, а затем для вызова процедуры генерируется инструкция CАLL. ЪДДДДДДДДДДДДДДДДДї директива inline ДД>і оператор inline ГДДДДДДДДДД> АДДДДДДДДДДДДДДДДДЩ Когда вы вызываете подставляемую процедуру (inline), компи- лятор генерирует код с помощью директивы inline, а не с помощью инструкции CALL. Таким образом, поставляемая процедура "расширя- ется" при каждом обращении к ней, аналогично макроинструкции на языке ассемблера. Приведем два небольших примера подставляемых процедур: procedure DisableInterrupts: inline($FA); { CLI } procedure EnableInterrupts; inline($FB); { STI } Примечание: Синтаксические диаграммы оператора inline описаны подробно в Главе 25. Описания функций ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание функции определяет часть программы, в которой вы- числяются и возвращается значение. ЪДДДДДДДДДї ЪДДДї ЪДДДДДДДї ЪДДДї описание ДДД>ізаголовокГДД>і ; ГДД>і тело ГДД>і ; ГДД> функции і функции і АДДДЩ іфункцииі АДДДЩ АДДДДДДДДДЩ АДДДДДДДЩ ЪДДДДДДДДї ЪДДДДДДДДДДДДДї заголовок ДДД>іfunctionГВ>іидентификаторГДДВДДДДДДДДДДДДДДДДДДДї функции АДДДДДДДДЩі АДДДДДДДДДДДДДЩ^ і ЪДДДДДДДДДДї ^ і і ЪДДДДДДДДДДДДДїі і ісписок і і і А>і уточненный ГЩ АД>іформальныхГДДЩ і іидентификаторі іпараметрові і і метода і АДДДДДДДДДДЩ і АДДДДДДДДДДДДДЩЪДДДДДДДДДДДДДДДДДДДДДЩ і ЪДДДї ЪДДДДДДДДї АД>і : ГДД>ітип ре- ГДД> АДДДЩ ізультатаі АДДДДДДДДЩ ЪДДДДДДДДДДДДДї тип результата ДДВДД>іидентификаторГДДДДДДДДД> і і типа і ^ і АДДДДДДДДДДДДДЩ і і ЪДДДДДДї і АДДДДД>іstringГДДДДДДДДДЩ АДДДДДДЩ Примечание: Функция не может возвращать процедурный тип или структурный тип. В заголовке функции определяется идентификатор функции, фор- мальные параметры (если они имеются) и тип результата функции. Функция активизируется при вызове функции. При вызове функ- ции указывается идентификатор функции и какие-либо параметры, не- обходимые для вычисления функции. Вызов функции может включаться в выражения в качестве операнда. Когда выражение вычисляется, функция выполняется и значением операнда становится значение, возвращаемое функцией. В операторной части блока функции задаются операторы, кото- рые должны выполняться при активизации функции. В модуле должен содержаться по крайней мере один оператор присваивания, в котором идентификатору функции присваивается значение. Результатом функ- ции является последнее присвоенное значение. Если такой оператор присваивания отсутствует или он не был выполнен, то значение, возвращаемое функцией, не определено. Если идентификатор функции используется при вызове функции внутри модуля-функции, то функция выполняется рекурсивно. Приведем далее примеры описаний функции: function Max(a: Vector; n: integer): extended; var x: extended; i: integer; begin x := a(1); for i := 2 to n do if x < a[i] then x := a[i]; Max := x; end; function Power(x: extended; y: integer): extended; var z: extended; i: integer; begin z := 1.0; i := y; while i > 0 do begin if Odd(i) then z := z*x; x := Sqr(x); end; Power := z; end; Аналогично процедурам функции могут описываться, как с ближ- ним типом вызова (near), с дальним типом вызова (far), опережаю- щие (forward), внешние (external), ассемблерные (assembler) или подставляемые (inline). Однако функции прерываний (interrupt) не допускаются. Описания методов ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Описание метода внутри объектного типа соответствует опере- жающему описанию (forward) этого метода. Таким образом, метод должен быть реализован где-нибудь после описания объектного типа и внутри той же самой области действия метода путем определяющего описания. Для процедурных и функциональных методов определяющее описа- ния имеет форму обычного описания процедуры или функции, за тем исключением, что в этом случае идентификатор процедуры или функ- ции рассматривается как идентификатор метода. Для методов конструкторов и деструкторов определяющее описа- ний принимает форму описания процедурного метода, за тем исключе- нием, что зарезервированное слово procedure заменяется на заре- зервированное слово constructor или destructor. Определяющее опи- сание метода может повторять (но не обязательно) список формаль- ных параметров заголовка метода в объектном типе. В этом случае заголовок метода должен в точности повторять заголовок в объект- ном типе в порядке, типах и именах параметров и в типе возвращае- мого функцией результата, если метод является функцией. В определяющем описании метода всегда присутствует неявный параметр с идентификатором Self, соответствующий формальному па- раметру-переменной, обладающему объектным типом. Внутри блока ме- тода Self представляет экземпляр, компонент метода которого был указан для активизации метода. Таким образом, любые изменения значений полей Self отражаются на экземпляре. Область действия идентификатора компонента объектного типа распространяется на блоки процедур, функций, конструкторов и деструктора, которые реализуют методы данного объектного типа. Эффект получается тот же, как если бы в начало блока метода был вставлен оператор with в следующей форме: with Self do begin ... end; Исходя из этих соображений, написание идентификаторов компо- нентов, формальных параметров метода, Self и любого идентификато- ра, введенного в исполняемую часть метода, должно быть уникаль- ным. Ниже приводятся несколько примеров реализаций методов: procedure Rect.Intersect(var R: Rect); begin if A.X < R.A.X then A.X := R.A.X; if A.X < R.A.Y then A.Y := R.A.Y; if B.X > R.B.X then B.X := R.B.X; if B.Y < R.B.Y then B.Y := R.B.Y; if (A.X >= B.X) or (A.Y >= B.Y) then Init (0, 0, 0, 0); end; procedure Field.Display; begin GotoXY(X, Y); Write(Name^, ' ', GetStr); end; function NumField.PutStr(S: string): boolean; var E: integer; begin Val(S, Value, E); PutStr := (E = 0) and (Value >= Min) and (Value <= Max); end; Конструкторы и деструкторы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Конструкторы и деструкторы являются специализированными фор- мами методов. Используемые в связи с расширенным синтаксисом стандартных процедур New и Dispose, конструкторы и деструкторы обладают способностью размещения и удаления динамических объек- тов. Кроме того, конструкторы имеют возможность выполнить требуе- мую инициализацию объектов, содержащих виртуальные методы. Как и все другие методы, конструкторы и деструкторы могут наследовать- ся, а объекты могут содержать любое число конструкторов и дест- рукторов. Конструкторы используются для инициализации вновь созданных объектов. Обычно инициализация основывается на значениях, переда- ваемых конструктору в качестве параметров. Конструктор не может быть виртуальным, так как механизм диспетчеризации виртуального метода зависит от конструктора, который первым совершил инициали- зацию объекта. ЪДДДДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДДДї ЪДДДї описание ДДД>і заголовок ГДД>і ; ГДД>і блок ГДД>і ; ГД> конструктора іконструктораі АДДДЩ іподпрограммыі АДДДЩ АДДДДДДДДДДДДЩ АДДДДДДДДДДДДЩ ЪДДДДДДДДДДДї ЪДДДДДДДДДДДДДї заголовок ДДДД>іconstructorГВ>іидентификаторГДВДДДДДДДДДДДДДДДД> конструктора АДДДДДДДДДДДЩі АДДДДДДДДДДДДДЩ^і ЪДДДДДДДДДДї ^ і ЪДДДДДДДДДДДДДїіі і список і і А>і уточненный ГЩАД>іформальныхГДЩ іидентификаторі іпараметрові і метода і АДДДДДДДДДДЩ АДДДДДДДДДДДДДЩ Приведем несколько примеров конструкторов: constructor Field.Copy(var F: Field); begin Self := F; end; constructor Field.Init(FX, FY, FLen: integer; FName: string); begin X := FX; Y := FY; GetMem(Name, Length (FName) + 1); Name^ := FName; end; constructor TStrField.Init(FX, FY, FLen: integer; FName: string); begin inherited Init(FX, FY, FLen, FName); Field.Init(FX, FY, FLen, FName); GetMem(Value, Len); Value^ := ''; end; Главным действием конструктора порожденного (дочернего) ти- па, такого как указанный выше TStrField.Init, почти всегда явля- ется вызов соответствующего конструктора его непосредственного родителя для инициализации наследуемых полей объекта. После вы- полнения этой процедуры, конструктор инициализирует поля объекта, которые принадлежат только порожденному типу. Деструкторы ("сборщики мусора") являются противоположностями конструкторов и используются для очистки объектов после их ис- пользования. Обычно очистка состоит из удаления всех полей-указа- телей в объекте. Примечание: Деструктор может быть виртуальным и часто является таковым. Деструктор редко имеет параметры. Приведем несколько примеров деструкторов: destructor Field.Done; begin FreeMem(Name, Length (Name^) + 1); end; destructor StrField.Done; begin FreeMem(Value, Len); Field.Done; end; Деструктор дочернего типа, такой как указанный выше TStrField.Done, обычно сначала удаляет введенные в порожденном типе поля указателей, а затем в качестве последнего действия вы- зывает соответствующий сборщик деструктор непосредственного роди- теля для удаления унаследованных полей-указателей объекта. Восстановление ошибок конструктора ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Borland Pascal позволяет вам с помощью переменной HeapError модуля System (см. Главу 21) установить функцию обработки ошибки динамически распределяемой области. Эта функциональная возмож- ность влияет на способ работы конструкторов объектного типа. По умолчанию, когда для динамического экземпляра объекта не хватает памяти, вызов конструктора, использующий расширенный син- таксис стандартной процедуры New, генерирует ошибку этапа выпол- нения 203. Если вы установили функцию обработки ошибки динамичес- ки распределяемой области, которая вместо стандартного результата функции 0 возвращает 1, когда выполнить запрос невозможно, вызов конструктора через New возвращает nil (вместо прерывания програм- мы). Код, выполняющий распределение памяти и инициализацию поля таблицы виртуальных методов (VMT) динамического экземпляра объек- та является частью последовательности вызова конструктора. Когда управление передается на оператор begin операторной части конс- труктора, память для экземпляра уже выделена, и он инициализиро- ван. Если выделения памяти завершается неудачно, и если функция обработки ошибки динамически распределяемой области памяти возв- ращает 1, конструктор пропускает выполнение операторной части и возвращает значение nil. Таким образом, указатель, заданный в вы- полняемом конструктором вызове New, устанавливается в nil. Когда управление передается на оператор begin операторной части конструктора, для экземпляра объектного типа обеспечивается успешное выполнение памяти и инициализация. Сам конструктор может попытаться распределить динамические переменные для инициализации полей-указателей в экземпляре, однако, такое распределение может завершиться неудачно. Если это происходит, правильно построенный конструктор должен отменять все успешные распределения и, нако- нец, освобождать выделенную для экземпляра объекта память, так что результатом может стать указатель nil. Для выполнения такой "отмены" Borland Pascal реализует стандартную процедуру Fail, ко- торая не требует параметров и может вызываться только из конс- труктора. Вызов Fail приводит к тому, что конструктор будет осво- бождать выделенную для динамического экземпляра память, которая была выделена перед входом в конструктор, и для указания неудачи возвращает указатель nil. Когда память для динамических экземпляров выделяется с по- мощью расширенного синтаксиса New, результирующее значение nil в заданном указателе-переменной указывает, что операция заверши- лась неудачно. К сожалению, не существует такого указателя-пере- менной, которую можно проверить после построения статического эк- земпляра или при вызове наследуемого конструктора. Вместо этого Borland Pascal позволяет использовать конструктор в виде булевс- кой функции в выражении: возвращаемое значение True указывает на успешное выполнение, а значение False - не неуспешное выполнение из-за вызова в конструкторе Fail. На диске вы можете найти две программы - NORECVER.PAS и RECOVER.PAS. Оба программы реализуют два простых объектных типа, содержащих указатели. Первая программа не содержит восстановления ошибок конструктора. Программа RECOVER.PAS демонстрирует, как можно переписать исходный код для реализации восстановления ошибки. Заметим, что для отмены успешного выделения памяти перед вызовом Fail для ито- гового неуспешного выполнения используются соответствующие дест- рукторы в Base.Init и Derived.Init. Заметим также, что в Derived.Init вызов Base.Init содержится внутри выражения, так что можно проверить успешность выполнения наследуемого конструктора. Параметры ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В описании процедуры или функции задается список формальных параметров. Каждый параметр, описанный в списке формальных пара- метров, является локальным по отношению к описываемой процедуре или функции и в модуле, связанным с данной процедурой или функци- ей на него можно ссылаться по его идентификатору. ЪДДДї ЪДДДДДДДДДДї ЪДДДї список формальных ДДД>і ( ГДДДДД>і описание ГДДВДД>і ) ГДД> параметров АДДДЩ ^ іпараметра і і АДДДЩ і АДДДДДДДДДДЩ і і ЪДДДї і АДДДДДДґ ; і<ДДДДДЩ АДДДЩ ЪДДДДДДДДДДДДДї описание ДДВДДДДДДДДДДДД>ісписок иден- ГВДДДДДДДДДДДДДДДДДДДДД> параметра і ЪДДДї ^ ітификаторов іі ^ ГД>іvarГДДДДґ АДДДДДДДДДДДДДЩі ЪДДДї ЪДДДДДДДї і і АДДДЩ і А>і : ГД>ітип па-ГДЩ і ЪДДДДДї і АДДДЩ іраметраі АД>іconstГДДЩ АДДДДДДДЩ АДДДДДЩ Существует три типа параметров: значение, переменная и нети- пизированная переменная. Они характеризуются следующим: 1. Группа параметров без предшествующего ключевого слова является списком параметров-значений. 2. Группа параметров, перед которыми следует ключевое слово const и за которыми следует тип, является списком пара- метров-констант. 3. Группа параметров, перед которыми стоит ключевое слово var и за которыми следует тип, является списком нетипи- зированных параметров-переменных. 4. Группа параметров, перед которыми стоит ключевое слово var или const за которыми не следует тип, является спис- ком нетипизированных параметров-переменных. Параметры строкового типа и массивы могут быть открытыми па- раметрами. Параметры-переменные, описанные с помощью идентифика- тора OpenString или с использованием ключевого слова string в состоянии {$P+}, являются открытыми строковыми параметрами. Зна- чение, константа или параметр-переменная, описанные с помощью синтаксиса array of T, являются открытым параметром-массивом. Примечание: Подробнее об открытых параметрах рассказы- вается ниже. Параметры-значения ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Формальный параметр-значение обрабатывается, как локальная по отношению к процедуре или функции переменная, за исключением того, что он получает свое начальное значение из соответствующего фактического параметра при активизации процедуры или функции. Из- менения, которые претерпевает формальный параметр-значение, не влияют на значение фактического параметра. Соответствующее фактическое значение параметра-значения должно быть выражением и его значение не должно иметь файловый тип или какой-либо структурный тип, содержащий в себе файловый тип. Фактический параметр должен иметь тип, совместимый по прис- ваиванию с типом формального параметра-значения. Если параметр имеет строковый тип, то формальный параметр будет иметь атрибут размера, равный 255. Параметры-константы ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Формальные параметры-константы работают аналогично локальной переменной, доступной только по чтению, которая получает свое значение при активизации процедуры или функции от соответствующе- го фактического параметра. Присваивания формальному парамет- ру-константе не допускаются. Формальный параметр-константа также не может передаваться в качестве фактического параметра другой процедуре или функции. Параметр-константа, соответствующий фактическому параметру в операторе процедуры или функции, должен подчиняться тем же прави- лам, что и фактическое значение параметра. В тех случаях, когда формальный параметр не изменяет при вы- полнении процедуры или функции своего значения, вместо парамет- ра-значения следует использовать параметр-константу. Парамет- ры-константы позволяют при реализации процедуры или функции защи- титься от случайных присваиваний формальному параметру. Кроме то- го, для параметров структурного и строкового типа компилятор при использовании вместо параметров-значений параметров-констант мо- жет генерировать более эффективный код. Параметры-переменные ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Параметр-переменная используется, когда значение должно пе- редаваться из процедуры или функции вызывающей программе. Соот- ветствующий фактический параметр в операторе вызова процедуры или функции должен быть ссылкой на переменную. При активизации проце- дуры или функции формальный параметр-переменная замещается факти- ческой переменной, любые изменения в значении формального пара- метра-переменной отражаются на фактическом параметре. Внутри процедуры или функции любая ссылка на формальный па- раметр-переменную приводит к доступу к самому фактическому пара- метру. Тип фактического параметра должен совпадать с типом фор- мального параметра-переменной (вы можете обойти это ограничение с помощью нетипизированного параметра-переменной). Примечание: Файловый тип может передаваться только, как параметр-переменная. Директива компилятора $P управляет смыслом параметра-пере- менной, описываемого с ключевым словом string. В состоянии по умолчанию ({$P-}) string соответствует строковому типу с атрибу- том размера 255. В состоянии {$P+} string указывает, что параметр является открытым строковым параметром (см. ниже). При ссылке на фактический параметр-переменную, связанную с индексированием массива или получением указателя на объект, эти действия выполняются перед активизацией процедуры или функции. Правила совместимости по присваиванию для объектного типа применяются также к параметрам-переменным объектного типа. Для формального параметра типа T1 фактический параметр должен быть типа T2, если T2 находится в домене T1. Например, с учетом опи- саний Главы 4, методу TField.Copy может передаваться экземпляр TField, TStrField, TNumField, TZipField или любой другой экземп- ляр потомка TField. Нетипизированные параметры ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД Когда формальный параметр является нетипизированным парамет- ром-переменной, то соответствующий фактический параметр может представлять собой любую ссылку на переменную или константу, не- зависимо от ее типа. Нетипизированный параметр, описанный с клю- чевым словом var, может модифицироваться, а нетипизированный па- раметр, описанный с ключевым словом const, доступен только по чтению. В процедуре или функции у нетипизированного параметра-пере- менной тип отсутствует, то есть он несовместим с переменными всех типов, пока ему не будет присвоен определенный тип с помощью присваивания типа переменной. Приведем пример нетипизированных параметров-переменных: function Equal(var source,dest; size: word): boolean; type Bytes = array[0..MaxInt] of byte; var N: integer; begin N := 0; while (N |