составные типы данных, операции над ними




связывание.

ОД(объект данных) – переменные, константы – абстрактное место, где могут храниться данные.

Виды связывания:

1) Статическое – в момент трансляции, сборка(линковка) – с точки зрения ЯП.

2) Динамическое – во время работы программы - между ОД и его значением: V=30;

3) Квазистатическое (константы: const C = 20;)

Большинство императивных ЯП – статическое связывание.

Java Scrypt, php … – динамическое связывание. (в основном такие языки являются интерпретируемыми).

Ада 83: Любой ОД имеет тип.

В традиционных ЯП – любой ОД имеет единственный тип.

ООЯП – любой ОД имеет статический тип. (Base d;)

Однако некоторые ОД могут иметь динамический тип.

С++: указатели и ссылки.(Base* p;)

Определяющее вхождение исключений – это ловушка:

catch(T e) { … }

Происходит динамически (даже в статических ЯП – С++)

Статические проверки – проверки при компиляции программы. Проверяемые данные не меняются в различных вызовах функции (запусках программы)

A:array [1..100] of integer;

……….

a[10] = 10; Статическая проверка

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

функции (запусках программы). Поэтому эти проверки делаются именно при выполнении.

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

a:array [1..100] of integer;

……….

a[n] = 10; n не известна в момент компиляции. Если язык поддерживает

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

В машинных языках нет квазистатических проверок. Поэтому нет и в Си.

В каких классах памяти могут размещаться данные в языках

программирования? В каких классах памяти размещаются объекты классов

языка С#?

Классы памяти:

• статическая;

• квазистатическая;

• динамическая.

В языке C# объекты классов размещаются только в динамической памяти.

2. Базисные типы данных в языках программирования: простые и

составные типы данных, операции над ними

Арифметические типы данных: целые, плавающие, фиксированные.

Фиксация представления: Java, C#.

Диапазон: все остальные

Проблемы представления чисел и способы их решения в ЯП.

Беззнаковые.

Есть неявное приведение: С++ и С.

Приведение только явное: в Модуле-2 существовали два типа INTEGER и CARDINAL. И приведение одного в другой допускалось только явное (существовал специальный оператор для такого присваивания):

I:INTEGER; J:CARDINAL; I:= INTEGER(J);

В Обероне существует лишь один беззнаковый тип byte(0..255)

Так в С# решили допускать только расширяющиеся преобразования (так как они безопасные). Обратные преобразования допускались только явно.

Ада: Они ввели обобщенные числовые типы данных. Объекты разных типов были несовместимы ни по какому множеству операций, но были совместимы объекты подтипов. То есть разные подтипы совместимы между собой и со своим предком.

Type Length is new integer;

Type Width is new integer;

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

Type Length in new integer range 0..MAXN.

В чем плюс обобщенных типов, так это что все ошибки обнаруживались на этапе компиляции.

Если требовались неявные преобразования, вводились подтипы.

Sybtype t1 is t2 range 0..N.

И тогда преобразования из T1 в T2 допускались. При этом компилятор сам выбирает

оптимальное представление для таких чисел. Теперь компилятор транслируя присваивание таких типов данных либо проверяет возможность такого присваивания на этапе трансляции, или же вставляет код по проверке допустимости такого присваивания (квазистатический контроль). В случае ошибки выхода за границу в Ада возбуждается range error.

Символьные и логические типы данных

Aда: type Boolean is (False, True); // представление типа Boolean

p: Boolean:= True;

...

if p then

...

end if;

C#, C, Java, Algol: bool p;

Кстати С единственный язык с неявным преобразование int в bool

Delphi, Pascal: var p:boolean

Порядковые типы: диапазоны и перечисления. Особенности реализации перечислений в современных ЯП.

Диапазоны

Паскаль

var

x: L..R;

Модула 2

var

x: [0..N];

y: CARDINAL[0..N];

i:INTEGER;

j:CARDINAL;

x:= 0; Проверки не будет

x:= i; Вставка квазистатической проверки, если нельзя вычислить i

x:= y; Проверки не будет.

Ада

Type Diap is range 0..N;

Type Pos is new INTEGER range 0..MAX_INT; новый тип данных.

….

I:integer;

Subtype Natural is range 1..MAX_INT;

J:Natural

………

I:= J; Проверки не будет

J:= I; В этой строчке будет проверка

Ни в одном из современных языков программирования нет типов-диапазонов, т.к. в современных языках чётко определены индексы массив: 0 <= i <= N-1, а основной областью применения диапазонов было именно задание типов индекса массива.

Перечисления

Паскаль:

Type EnumTyp = (va1, …, valN);

Операции:

:=, =, <, >, <>, >=, <= - основаны на функциях succ(x), pred(x), ord(x) = 0…N-1 (Элементы упорядочены)

Модула-2

type ET = (v1, …, vN);

Преобразования:

ord(x); ET -> integer

val(T,i); ET -> integer. Либо выдаёт ошибку, либо выдаёт значение val(ET,v2) = 1;

В Си-89 добавили такую конструкцию:

enum ET(v0,…,vN);

которая эквивалентна последовательности строк

#define v0 0;

#define v1 1;

……..

В Си++ можно задавать значения константам перечисления

Enum FileAccept

{

FileRead = 1;

FileWrite = 2;

FileReadWrite = FileRead | FileWrite;

}

Удобство использования такое же, как и для int

Ада

Типы BOOLEAN и CHARACTER являются перечислимыми типами данных из пакета

STANDARD

Проблема неявного импорта:

type SendColor is (Red,Yellow,Green)

type BasicColor is (Red,Green,Blue)

Ввели понятие «литерал» перечисления. Им является либо идентификатор, либо символ (‘символ’)

type Latin is (‘A’, ‘B’,’C’,…,’Z’)

type ASCII Latin(‘A’, ‘B’,’C’,…,’Z’, ‘a’, ’b’,…)

Литерал перечисления – функция без параметров, имя которой совпадает с литералом и

возвращает нужную константу

Решение проблемы неявного импорта:

Уточнение типа - T’expr – выражение expr трактовать как выражение типа Т

P(BasicColor’Red) – правильно!

Представление:

for BasicColor use (Red => FF00000x, Green => FF00x, Blue =>FFx)

for BasicColor’Size use 24; - 24- количество битов

«’» специальная операция, применимая именами типов, позволяющая получить доступ к

некоторым атрибутам

C#

По умолчанию базовый_целый_тип — это int.

Каждая константа в списке может быть инициализирована своим

значением (как в Си++).

enum BasicColor

{

Red = 0xFF0000;

Green = 0xFF00

Blue = 0xFF

};

enum SendColor: Byte

{

Red;

Yellow;

Green;

};

Преобразования из перечислимых типов в целочисленные в современных языках только

явные.

Атрибуты – средства сообщать компилятору некоторую информацию о реализации типа.

[FLAGS] – указывает, что к элементам перечисления применимы побитовые операции | и &.

[FLAGS]

enum FileAcces

{

FileRead = 1;

FileWrite = 2;

FileReadWrite = FileRead | FileWrite;

}

теперь, если вывести на экран FileAccept. FileReadWrite получим «FileRead, FileWrite». Без

использования атрибута [FLAGS] получим 3.

С#, Java

Неявный импорт

Константы из перечислимого типа видимы только потенциально и при

обращении должны уточняться именем типа: тип.имя_константы.

Пример:

enum Color: long

{

Red,

Green = 50,

Blue

}

Color c = Color.Red

FileAcces x;

X = FileAcces.Read; //Уточнение перечисления

Для каждого типа-значения существует класс-обёртка

С# int - Int32,bool – Boolean, long – Int64

Java int – Integer,bool – Boolean, long – Long

В С# все обёртки находятся в.Net

Для всех перечислений имеется один класс-обёртка – «Enum» всем перечислениям доступны методы класса Enum ToString(), GetValues() и т.д.

преобразования:

EnumType -> Integer безопасно

Integer -> EnumType Небезопасно. Нужны проверки.

uses (pascal, Ада) Вместе с перечислимым типом неявно импортируются все его константы на том же уровне видимости. Таким образом значения констант могут конфликтовать и перекрываться для разных перечислимых типов (в т.ч. из разных модулей).

Перечислимых типов нет: «Оберон»(1988) и «Оберон-2»(1993), Java (1995), но Java (2005) - расширение Java, в том числе добавление перечислимых типов, оформленных в виде полноценных классов.

Ссылки и указатели. Управление памятью. Автоматическая сборка

мусора. Объектно-референциальная модель в современных ЯП.

Строгие

Стандартный Паскаль, Модула-2, Ада, Оберон (со сборкой)

Pascal

Type PT = ^T;

{ Modula-2

Type PT = pointer to T;}

var

i:T;

Инициализировать указатель можно только двумя способами – либо другим указателем,

либо выделением новой памяти NEW(p: PT). Поэтому все данные чётко разделяются на

именованные, либо не именованные. Указатель служит для работы с анонимными данными в динамической памяти.

Не строгие

C, C++, Turbo Pascal

Можно получать адрес любого объекта с помощью операции взятия адреса «&»

Существует абстрактный указатель «void *»

T * => void * автоматически

void * к T * автоматически не приводится

T * p;

void *pp;

pp = p;

p = (T *)pp;

Проблемы строгих и нестрогих указателей:

• Удаление памяти (Dispose(p: PT)) не в своё время, что приводит к появлению «висячих ссылок» - указателей, которые должны на что-то указывать, но не указывают.

• Накопление мусора – памяти, на которую не указывает ни один указатель.

Различают системы с динамической сборкой мусора и без таковой.

Строгий язык с динамической сборкой мусора довольно надёжен.

От висячих ссылок защиты нет

Ада

В чистой Аде есть только new(p). В модуле STANDARD есть UNCHECKED_DEALLOCATION(p) – подчёркивается небезопасность этой операции. Так процедура UNCHECKED_DEALLOCATION(P) является аналогом delete(p), dispose(p) в ЯП, где используется динамическая сборка мусора.

C#, Java - понятие указателя отсутствует (точнее в C# такое понятие есть, но только в небезопасных блоках unsafe)

X a; // Если в C#, Java – то объект является ссылкой и пока не существует.

a = new X(); //Вызов конструктора обязателен.

a = b; // Присваивание ссылок, а не копирование.

Ада 83:

PT – указатель на тип T.

type PT is access T;

x: PT;

x:= new T;

y: T; - Получить адрес у стандартными средствами нельзя.

Ада 95:

Если: type PT is access T;

То инициализация возможна только так:

x: PT;

x:= new T;

Если же: type PTT is access all T; (на все объекты типа Т)

xx: PTT;

xx:= new T;

Однако можно ссылаться и на другие переменные:

z: aliased T;

zz: T;

z ’access – операция взятия адреса.

x:= z’access; - нельзя, т.к. без aliased.

xx:= z’access; -можно.

xx:= x; - можно.

x:= xx; - нельзя.

В современных ЯП ссылки – это средства доступа к объекту.

В C#, Java, Delphi – имеются референциальные ТД. “имена” = ссылки.

В С++ добавили отдельный базисный тип - ссылочный.

2. Назовите две причины большей надежности указателей языка Ада 83

по сравнению с указателями языка Си++.

Указатели языка Ада 83 ссылаются только на объекты из динамической памяти. Указатель языка Си++ может ссылаться на любой объект данных (динамический, локальный, статический), что может приводить к труднообнаружимым ошибкам.

Также в языке Ада отсутствует адресная арифметика (арифметические операции над указателями), что также уменьшает вероятность появления ошибки работы с памятью.

Составные типы данных.

Массивы и их особенности в современных ЯП.

Последовательность однотипных элементов.

D x … x Dn

A[i] – операция индексирования. i – индексное выражение.

Атрибуты массива:

1)Базовый тип (тип элементов) – D

2)Тип индекса (i)

3)Диапазон индекса (длина)

В разных ЯП:

Связывание базового типа статически (везде).

Тип индекса – С/С++/С#/Java/Оберон – всегда тип int (статическое связывание).

Фиксируется нижняя граница значения индекса.

Длина – статическая и динамическая.

Динамическая – чисто-динамическая (можно изменить в любое время) и квазистатическая (значение получено динамически, но изменять нельзя).

Можно длину сделать статической (жестко), оттого сделали квазистатической.

T[] a = new T[N]; //0..N-1

Модула-2:

Понятие открытого массива: зафиксирован базовый тип.

TYPE Arr = ARRAY Index of D;

TYPE Index = [1..N];

ARRAY of D;

Для типа CARDINALL:

Index = CARDINALL[0..N]; //В данном случае индекс задается статически.

//процедура суммирования элементов массива

PROCEDURE SUM (VAR A: ARRAY OF REAL): REAL;

//для любого открытого массива применима функция HIGH –она возвращает //максимальное значение индекса или -1.

VAR S: REAL; I: INTEGER;

BEGIN

S:=0.0;

FOR I:=0 TO HIGH(A) DO

S:=S+A[I];

END;

RETURN S;

END SUM;

Общий синтаксис объявления массива в Обероне

TYPE Arr = ARRAY N OF D;

При таком объявлении N, очевидно, является константой, длина массива – статический атрибут, что позволяет максимально эффективно распределять память. Таким образом

1) распределение памяти отчасти чисто статическое

2) квазистатические атрибуты длины возможны в качестве формальных аргументов

А собственно память распределяется чисто статически.

Механизм типа-подтипа в Ада

Подтип может ограничивать значения базового типа.

Пример

Тип диапазон:

TYPE NAT IS NEW INTEGER RANGE 1..MAX_INT (NEW – означает новый тип)

X: NAT;

Подтип:

SUBTYPE POS IS INTEGER RANGE 0..MAX_INT;

X: POS; I: INTEGER;

I:=X; X:=I ~ X:=POS(I);

Неограниченный тип массива.

D,I – зафиксированы.

L..R – не фиксируемые левые и правая границы.

Итак, в Ада существует 2 типа массивов:

1) регулярный ограниченный – тут фиксируется ВСЕ

TYPE TARR IS ARRAY INTEGER RANGE 0..N of REAL;

2) неограниченный регулярный тип

Разница между первым и вторым типами заключается во времени связывания атрибута длины.

Атрибуты регулярного типа:

A’LENGTH – длина массива

A’FIRST = L

A’LAST = R

A’RANGE = RANGE A.FIRST..A.LAST

У неограниченных типов данных – атрибуты динамические, у ограниченных – статические.

Можно считать, что неограниченный регулярный тип в Ада – это обобщение понятия открытого массива. Ограниченный регулярный тип применим к любому базовому типу. Если мы объявляем объект данных, то его тип должен быть обязательно ограниченным, а объекты неограниченных типов данных могут быть лишь формальными параметрами процедур и функций.

Зачем нужны неограниченные типы данных: они нужны для выведения из них других типов данных.

X1: TARR; //ограниченный тип данных

Таким образом, объявление переменной корректно, если компилятор может распределить память

X2: Arr; //Нельзя. Компилятор не может распределять память.

Надо: X2: Arr range 0..N;

Мы вполне можем написать функцию, к примеру, суммирующую все элементы неограниченного регулярного массива:

Function SUM(A: Arr)return real is

S: real:= 0.0;

Begin

for i in A’RANGE loop S:=S+A(i); end loop;

 

return S;

end SUM.

Смысл такой же: описав объект неограниченного типа, мы можем передавать в качестве фактического параметра конкретный объект, принадлежащий, естественно, ограниченному типу.

a:=SUM(X2);

Статически все подтипы одного типа совместимы между собой как объекты одного типа. Но при присваивании объекта одного типа другому компилятор вставляет квазистатический контроль.

В стандарте языка Ада принято решение: если длины массивов совпадают, то присваивание возможно, даже если диапазоны рознятся.

Динамический массив (квазистатический).

Такой массив может быть только локальной переменной.

Динамический массив – это локальный массив, левая и правая граница которого определяются при входе в соответствующий блок.

procedure P(N: integer) is

A: array(1..N) of real;

В языке Oberon есть разница между чисто статическими объектами данных и открытыми массивами. В C# и Java длина массива квазистатическая.

C#, Java:

T[] имя;

new имя[len];

int[] a = new int{1,2,3,4,5}; (С#)

В C# и Java a[i](выход за границы массива) контролируется квазистатически.

Многомерные массивы.

С, С++: int a[N1][N2];

C#: int [,] a = new a[N1,N2];

int a[ ][ ]; //ступенчатый массив, он же разрывный.

Элементы ступенчатого массива представляют собой ссылки на соответствующие объекты (массивы).

Пример инициализации подобного массива:

a = new int [ ] [3];

a[0] = new int[1];

a[1] = new int[2];

a[2] = new int[3];

Вырезка: подмножество элементов массива.

Фортран:

А(N1,N2)

А(1,*) – 1-я строчка.

А(*,1) – 1-й столбец.

A(2..5,*), A(1..3,2..4) – прямоугольная вырезка.

Ада поддерживает только одномерные непрерывные вырезки.

В остальных нет.

Замечание: в языках Оберон и Модула-2 длина формальных

параметров — открытых массивов является динамическим атрибутом. В

других случаях длина массива — статический атрибут. В Аде формальные параметры неограниченных типов-массивов также имеют динамический

атрибут-длину (равно как и динамические массивы-локальные переменные).

Записи. Недостатки системы типов в традиционных ЯП. Объединения

как средство преодоления этих недостатков. Проблемы, связанные с

объединениями.

struct name {поля}

record последовательность полей end;

Запись – это набор переменных, с которыми можно обращаться как с единым целым.

Задавая набор полей, мы задаем запись(id – идентификатор поля, T – тип поля):

(id1, T1)

(id2, T2)

(idN, TN)

Разные типы: тип ó класс обертка (упаковка, распаковка)

Java: отсутствует запись – она не нужна. В Обероне есть, но с другим смыслом.

С++: класс – обобщение структуры. (у структур в С собственное пространство имен)

Отличия:

1) Имена (структура может быть анонимной)

2) struct – public, class – private.

Delphi:

Новое – класс.

Старое – record.

C#: Типы – значения.

struct c {}

class F{}

С а = new C();

Отличия от класса:

1)память распределена под типы-значения (если локально – то память под структуры выделяется в стеке)

2) все структуры неявно наследуются из класса Object, но сами наследоваться не могут.

Следует отметить одно из странных свойств структуры в языке С#: у нее нельзя переопределять конструктор по умолчанию. Сделано это было с целью увеличения эффективности языка C#, чтобы впоследствии сделать его моноязыком под.Net.

В случае, когда мы заводим массив из объектов классов, в силу того, что классы – это объекты референциального типа, мы получаем не массив из объектов, а массив из ссылок на объекты.

class Point { int x,y; }

Point[] pointArray = new Point[1000];

Для создания самих объектов необходимо для каждого i написать:

Pts[i]=new Point(); //Неоправданные затраты памяти и времени. Здесь лучше использовать

структуру.

Объединение типов (или запись с вариантами) — это конструкция, объединяющая в один тип несколько различных структур (вариантов). Все варианты в объединении начинаются с одного адрес и занимают одну и ту же память.

Размеченное объединение типов содержит одно выделенное поле (дискретного типа данных) — общее для всех вариантов. Такое поле называется дискриминантом. Значение дискриминанта определяет, по какому варианту выделена память в переменной-экземпляре



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: