http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 

Паскаль для новичков (часть 5)

 

Совместимость типов

 
Автор: Владислав Демьянишин
 
Паскаль для новичковСегодня мы поговорим о совместимости типов.
В чистом виде эквивалентность (равенство) типов переменных или значений параметров требуется только в случае передачи параметров при вызове процедур или функций (таким образом типы фактических, т.е. передаваемых, и формальных, т.е. требуемых, параметров должны быть эквиваленты). В других Pascal-конструкциях используются несколько ослабленные (но более детальные) ограничения, называемые СОВМЕСТИМОСТЬЮ типов.
 
Выполнение операций в выражениях, а также операции сравнения переменных требуют, чтобы операнды имели совместимые типы. Совместимость типов двух переменных (или некоторых значений) имеет место, если выполняется хотя бы одно из следующих условий:
1) Два типа эквивалентны (равны);
2) Оба типа являются либо целыми, либо оба типа являются вещественными;
3) Один тип является ограниченным типом, причем его базовым типом является другой тип:
 
type
T1 = shortint;
T2 = 1..100;
 
т.е. тип T2 может иметь значения в диапазоне 1..100, и любое значение этого типа попадает в диапазон допустимых значений для типа Shortint (-128..127), стало быть, типы T1 и T2 совместимы, т.е. могут взаимно заменяться в выражениях и сравнениях;
4) Оба типа являются ограниченными, причем их базовым типом является один и тот же тип:
 
type
T1 = 10..100;
T2 = 1..5;
 
опять таки, типы T1 и T2, судя по диапазонам описанных для них значений, являются целыми, значит эти типы совместимы;
5) Оба типа являются множественными типами (см. главу “Множественные типы”), причем их базовые типы являются совместимыми:
 
type
T1 = set of byte;
T2 = set of 1..10;
 
здесь немного сложнее, но тот же принцип, множественный тип T2
может содержать значения в диапазоне 1..10, а такие значения может содержать и тип Byte, т.е. типы T1 и T2 совместимы;
6) Оба типа являются упакованными символьными массивами (см. главу “Составные типы. Регулярные типы (массивы)”) с одинаковым числом элементов;
 
7) Один тип является строковым (см. главу “Строковые типы”), а другой тип либо также является строковым типом, либо упакованным символьным массивом, либо символьным типом;
 
8) Один тип является ссылочным типом, а другой тип либо также является ссылочным типом, либо является бестиповым указателем (см. главу “Ссылочные типы. Динамические переменные”);
 
9) Оба типа являются процедурными типами (см. главу “Процедуры и функции”) с одинаковым числом параметров, типы которых эквивалентны (соответствие по порядку перечисления в описании процедурного типа), и (для функциональных типов) с эквивалентными типами возвращаемого результата.
 
Здесь я забежал немного вперед. Сейчас не стоит глубоко задумываться над последними пятью пунктами.
 
Для операторов присваивания имеется специальное понятие – совместимость по присваиванию. Оператор присваивания считается корректным, если тип переменной в левой части совместим по присваиванию с типом выражения из правой части.
 
левая часть = правая часть
 
Проще говоря, переменной одного типа (той что слева) можно присвоить значение переменной (или результата выражения) другого типа (той что справа), если типы этих переменных совместимы по присваиванию.
Два типа являются совместимыми по присваиванию, если выполняется хотя бы одно из следующих условий:
1) Оба типа эквивалентны и ни один из них не является файловым типом (см. главу “Файловые типы и ввод-вывод”) или не является структурным типом, содержащим поле с файловым типом на одном из своих уровней;
2) Оба типа являются совместимыми дискретными (целыми), и значения типа правой части попадают в диапазон возможных значений типа левой части (чтобы левая часть могла принять новое значение без возникновения ошибки от переполнения);
3) Оба типа являются вещественными типами, и значения типа правой части попадают в диапазон значений типа левой части;
4) Тип левой части является вещественным типом, а тип правой части является целым типом;
5) Тип левой части является строковым типом, а тип правой части – либо строковым типом, либо символьным типом, либо упакованным символьным массивом;
6) Оба типа являются совместимыми упакованными символьными массивами;
7) Оба типа являются совместимыми множественными типами, причем множество из правой части целиком входит во множество из левой части;
8) Оба типа являются совместимыми ссылочными типами, либо совместимыми процедурными типами;
9) Тип левой части является процедурным типом, а правая часть представляет собой идентификатор процедуры или функции, причем с таким же числом параметров, что и у типа левой части; типы параметров должны быть эквивалентны, так же, как и (для случая функции) эквивалентны типы возвращаемого результата;
10) Оба типа являются объектовыми типами, причем тип правой части является потомком типа левой части (см. главу “Средства объектно-ориентированного программирования”), либо оба типа являются ссылочными типами на совместимые объектовые типы.
 
Если в операторе присваивания не выполняется ни одно из этих условий, то на этапе компиляции или при выполнении программы выдается сообщение об ошибке.
 

Составные типы

 
Простые типы, о которых я рассказывал ранее, определяют различные множества атомарных (неразделимых) значений. Например, имеем переменную типа Longint, в которой все 4 байта (занимаемые ею в памяти) составляют какое-то единое числовое значение. Составные типы, или структурные типы, в отличие от простых, задают множества “сложных” значений; каждое значение из такого множества образует некоторый агрегат (совокупность) нескольких значений другого типа (или других типов). Можно сказать, что составные типы определяют некоторый способ образования новых типов из уже имеющихся, причем отдельные элементы составных значений могут иметь любой, в том числе составной, тип. Таким образом, Pascal допускает образование структур данных произвольной сложности, позволяя тем самым достичь адекватного представления в программе тех данных, с которыми она оперирует.
В Pascal определены следующие составные типы:
1) Регулярные типы (массивы);
2) Комбинированные типы (записи);
3) Множественные типы;
4) Строковые типы;
5) Файловые типы;
6) Объектовые типы.
 

Регулярные типы (массивы)

 
Регулярный тип или попросту массив – это последовательность определенного количества элементов одного типа. Такая последовательность является одним целым – группой и именуется одним именем, а доступ к каждому элементу массива осуществляется через указание индекса (некое подобие порядкового номера) этого элемента сразу за именем массива, что очень удобно при программировании.
Для корректного описания массива необходимо задать такие характеристики:
1) Общий тип для элементов массива, которым может быть любой базовый тип или произвольный тип, созданный самим программистом, короче - ЛЮБОЙ;
2) Общее количество элементов в массиве, например [0..100] или [1..101] или [-50..50] что приведет к созданию массива с количеством в 101 элемент в любом из этих случаев, с одной лишь разницей, что в первом случае элементы массива будут пронумерованы начиная с индекса (номера) 0 и заканчивая индексом 100, во втором случае с 1 до 101 и в третьем случае с -50 до 50. Т.е. сам программист волен решать, как должны нумероваться элементы в создаваемом массиве.
 
Описание регулярного типа или массива имеет следующий общий вид:
 
type
A = array [ T1 ] of T2;
 
где слова array и of – служебные слова, A – имя типа массива (как вы хотите его назвать), T1 – тип индекса массива, которым может быть любой дискретный (целый) или ограниченный тип, модуль значений которого не может превышать число 65535, т.е. все целые типы кроме типа Longint, а также допустимы перечислимые типы, T2 – базовый тип элементов массива.
Вот примеры описания массивов:
 
const
MaxPerson = 100;
 
type
TPerson = record
    Name : string[10];
    Age : byte;
    Address : string[50]
    end;
M1 = array [1..100] of real;
M2 = array [char] of boolean;
Matrix = array [1..10] of array [1..20] of integer;
TCustomer = array [1..MaxPerson] of TPerson;
 
var
Vector : M1;
Sys_Table : M2;
Arr1, Arr2 : Matrix;
S : array [(Red, Yellow, Green)] of boolean;
Customer : TCustomer;
 
В этом примере описана переменная Vector типа M1, который в свою очередь является массивом с элементами типа Real. Переменная Sys_Table моделирует некоторую логическую шкалу, в которой каждому символу (с типом Char) соответствует некоторое логическое значение, а доступ к элементам этого массива может быть организован так:
 
Sys_Table[‘a’] := true;
If Sys_Table[‘m’] then …
 
Переменные Arr1 и Arr2 типа Matrix, который является по сути двухмерным массивом 10x20 с типом Integer для каждого элемента массива. К элементам такого массива можно обращаться, например, так:
 
Arr1[5, 10] := 100;
Arr2[10, 15] := Arr1[10, 10];
 
Впрочем, для описания типа массива Matrix можно использовать более простую форму:
 
type
Matrix = array [1..10, 1..20] of integer;
 
Число индексов в определении массива (т.е. размерность) в языке не ограничивается, таким образом массив может быть как одномерный, так и двухмерный, трехмерный, четырех- и так далее. Красота ;o)
Переменная Customer имеет тип TCustomer, определяющий структуру данных в виде массива, каждый элемент которого является комбинированным типом или, проще говоря записью, состоящей из полей, которые могут содержать личную информацию о любом человеке (поля: Name - имя, Age - возраст, Address - адрес). К такому массиву можно обращаться так:
 
Customer[5].Name := ‘Владимир’;
Customer[25].Age := 19;
 
Переменная S описана как массив с индексами Red, Yellow, Green, перечислимого типа и элементами типа Boolean. Пример:
 
S[Yellow] := false;
 
При работе с массивами необходимо помнить об ограничении на размер общей памяти под переменные. Чаще всего предел в 64Кбайт бывает превышен из-за ошибочного описания массивов (либо состоящих из чрезмерного числа элементов, либо больших размеров этих элементов).
В авторской версии языка, а также в некоторых его реализациях имеется понятие упакованного массива, элементы которого хранятся в памяти максимально плотно, пусть даже в ущерб времени доступа к ним. Для задания таких массивов используется служебное слово packed, указываемое перед словом array, например:
 
type
MyVec = packed array [1..20] of single;
 
В целях совместимости с другими реализациями Tubo Pascal допускает такую форму записи, однако она никак не влияет на способ хранения массива, так как в любом случае компилятор обеспечивает наиболее компактное размещение элементов в памяти при достаточно высокой эффективности доступа к ним.
Все приведенные выше примеры демонстрировали использование массива поэлементно. А как же использовать его целиком? Pascal допускает единственно возможное действие над массивом в целом: использование его в операторе присваивания, например:
 
Vect1 := Vect2;
 
причем типы обоих массивов в данном случае должны быть эквивалентны.
В качестве индексов могут выступать произвольные выражения, тип которых должен соответствовать типу индексов в описании массива.
Так, доступ к элементам массива Vector, описанного выше, можно строить следующим образом:
 
Vector[1] := 0.31709;
Vector[(i + 1)*2] := Pi;
 
где i – переменная целого типа.
Двухмерный массив Arr1, описанный выше, допускает такой доступ к своим элементам:
 
Arr1[i, j] := 200;
 
Так как его можно трактовать как “массив массивов”, то конструкция
 
Arr1[k]
 
вполне допустима в языке и в данном случае обозначает k-ый массив в группе из 10-ти массивов. Для того, чтобы адресоваться, скажем, к 5-му элементу этого массива, можно записать:
 
Arr1[k][5] := 500;
 
Такая запись корректна, хотя можно использовать более компактную форму
 
Arr1[k, 5] := 500;
 
Каждый элемент массива считается переменной; он может получать значения (например, в операторе присваивания), а так же участвовать в выражениях, где он представляет значение, помещенное в соответствующий элемент данного массива. Ассортимент операций над элементами массива полностью определяется типом этих элементов (базовым типом массива).
Примеры:
 
Arr1[i, j] := Arr1[i, j-1] + 1;
Sys_Table[‘z’] := Switch and Sys_Table[‘a’];
 
Продолжение следует…
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > Паскаль для новичков (Turbo Pascal, Assembler) > Паскаль для новичков (часть 5). Совместимость типов (продолжение)
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы