|
Новости |
Глава 5. Переменные и типизированные константы·
Десигнаторы
компонентов объекта ·
Переменные-указатели
и динамические переменные ·
Константы
множественного типа Описания переменныхОписание переменной представляет собой список идентификаторов, которые обозначают новые переменные и их типы. Тип,
задаваемый для переменных, может быть
идентификатором типа, который был ранее
описан в разделе описания типов того же
самого блока, или блока, в который входит
данный блок, или модуля, или же этот тип
может быть новым определением типа. При
указании идентификатора в списке
идентификаторов описания переменной этот
идентификатор имеет силу идентификатора
переменной в том блоке, где это описание
было указано. К этой переменной можно
обращаться из любого места этого блока,
если ее идентификатор не переопределен в
блоке, входящем в первый. Переопределение
означает, что для новой переменной
используется тот же самый идентификатор, но
это использование не оказывает влияния на
значение первоначальной переменной. Приведем
пример раздела описания переменной: 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; Переменные,
описанные вне процедуры и функции,
называются глобальными переменными и
располагаются в сегменте данных. Переменные,
описанные в самой процедуре или функции,
называются локальными переменными и
располагаются в сегменте стека. Ссылки на переменныеСсылка
на переменную может обозначать следующее:
Синтаксис ссылки на переменную имеет вид: Отметим,
что синтаксис ссылки на переменную
допускает использование выражения,
вычисляющего значение ссылочного типа. Выражение
должно следовать за квалификатором,
разыменовывающим ссылочное значение (или
индексирующим значением указателя, если с
помощью директивы $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), и массив содержит
строку с завершающим нулем. При описании константы типа
"многомерный массив" константы каждой
размерности заключаются в отдельные скобки
и разделяются запятыми. Расположенные в
середине константы соответствуют самым
правым размерностям. Описание: 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); Поля
должны указываться в том же порядке, как они
следуют в описании типа запись. Если запись
содержит поля файлового типа, то для этого
типа запись нельзя описать константу. Если
запись содержит вариант, то можно указывать
только поля выбранного варианта. Если
вариант содержит поле признака, то его
значение должно быть определено. Константы множественного типаОписание
константы множественного типа может
содержать несколько элементов,
заключенных в квадратные скобки и
разделенных запятыми. Каждый элемент такой
константы представляет собой константу
или отрезок типа, состоящий из двух
констант, разделенных двумя точками. Приведем
несколько примеров констант-множеств: 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 = ( 'Ноль',
'Один', 'Два', 'Три', 'Четыре', 'Пять',
'Шесть', 'Семь', 'Восемь', 'Девять'); Результатом
будет то, что указатель теперь указывает на
область памяти, содержащую копию
строкового литерала с завершающим нулем. |
(с) Все права защищены. По всем интересующим вопросам прошу писать электронный адрес |