Методические указания для студентов 1 курса факультета математики, механики и компьютерных наук

Вид материалаМетодические указания

Содержание


1Указатели 1.1Общие сведения
1.2Неявные указатели
1.3Указатели pointer
1.4Динамическая память и динамические переменные
1.5Процедуры New и Delete
1.6Процедуры GetMem и FreeMem
1.7Ошибки при работе с динамической памятью
2Динамические структуры данных 2.1Общие сведения
2.2Односвязные линейные списки
2.3Сравнение списков и массивов
2.4Двусвязные линейные списки
3Абстрактные типы данных и их реализация. Классы
Абстрактный тип данных
3.1АТД «Стек» и его реализация с помощью модуля
Реализация АТД «Стек» на базе массива
Вычисление постфиксного выражения
Реализация АТД «Стек» на базе линейного списка
3.2Классы: основные понятия
Классы и объекты
Конструкторы и деструкторы
...
Полное содержание
Подобный материал:
  1   2   3   4   5   6   7   8


ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ


Федеральное государственное образовательное учреждение

высшего профессионального образования

«ЮЖНЫЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ»


С.С. Михалкович


Основы программирования

Указатели. Динамические структуры данных.

Абстрактные типы данных. Классы


МЕТОДИЧЕСКИЕ УКАЗАНИЯ

для студентов 1 курса

факультета математики, механики и компьютерных наук


Ростов-на-Дону

2007


Аннотация


Методические указания содержат лекции по темам «Указатели», «Динамические структуры данных», «Абстрактные типы данных» курса «Основы программирования» для студентов направления «Информационные технологии» факультета математики, механики и компьютерных наук


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


Печатается в соответствии с решением кафедры алгебры и дискретной математики факультета математики, механики и компьютерных наук ЮФУ, протокол № 3 от 13 ноября 2006 г.

1Указатели

1.1Общие сведения


Оперативная память компьютера может рассматриваться как массив байтов, индексируемый от нуля. Номер каждого байта в этом массиве называется его адресом. Адресом переменной называется адрес ее первого байта. Для получения адреса переменной в языке Pascal используется унарная операция @: @x – адрес переменной x.

Переменные, в которых хранятся адреса, называются указателями. Любой указатель в 32-разрядной операционной системе занимает 4 байта. Это дает возможность адресовать ячеек памяти. С переходом на 64-битные системы объем адресуемой оперативной памяти станет практически безграничным.

Для чего нужны указатели? Их использование повышает гибкость программирования и разграничивает обязанности: указатель знает лишь адрес переменной, сама переменная может менять свое значение независимо от наличия указателя на нее. Можно провести аналогию между указателями и справочной службой 09. Клиент обращается в справочную службу для того, чтобы узнать номер телефона абонента. Другими словами клиент обращается к указателю, который знает адрес объекта и, следовательно, может вернуть значение этого объекта (в данном случае – номер телефона). Гибкость такого способа очевидна: не следует помнить номера всех телефонов, достаточно знать номер телефона справочной. Кроме того, если номер телефона абонента будет изменен, то в справочной службе будет произведена оперативная корректировка информации, и при последующем обращении в службу клиент получит измененный номер телефона. Другой пример: несколько указателей (банкоматов) указывают на один объект (банковский счет). Посредством разных банкоматов можно снимать деньги с одного банковского счета. Третий пример: файловый указатель, который обращается всякий раз к текущему элементу файла, после чего перемещается на следующий. Это позволяет единым образом (через один указатель) работать с различными данными, находящимися в файле.

В языке Delphi Pascal указатели делятся на типизированные и бестиповые. Если T – некоторый тип, то типизированный указатель на него описываются следующим образом: T (указатель на тип). Бестиповой указатель описывается с помощью типа pointer. Если типизированный указатель хранит адрес переменной заданного типа, то бестиповой хранит просто адрес некоторого участка памяти.

Будем изображать тот факт, что указатель pa хранит адрес переменной a, следующим образом:



При этом говорят, что pa указывает на a. Указатель может также хранить специальное значение, задаваемое предопределенной константой nil. Это «нулевое значение» для указателей, означающее, что указатель никуда не указывает. Будем называть такой указатель нулевым и изображать его следующим образом:



Типизированные указатели разных типов несовместимы по присваиванию. Однако типизированный и бестиповой указатель совместимы по присваиванию в обе стороны. Указатели одного типа, а также типизированный и бестиповой указатель можно сравнивать на равенство и неравенство. Далее приводятся примеры допустимых действий с указателями:

var a: integer;

r: real;

    pa,pa1: integer;

p,p1: pointer;

pr: real;

begin

  pa:=@a;

p:=@a;

pa:=p;

p:=pa;

p:=nil;

pa:=nil;

if pa=pa1 then ;

if pa<>p then ;

...

Следующие действия, наоборот, являются недопустимыми и вызовут ошибку компиляции, поскольку выполняются над указателями, имеющими различный базовый тип:

pr:=pa; // ошибка: несовместимые типы

if pr=pa then; // ошибка: несовместимые типы

Следует помнить, что в языке Pascal принята именная эквивалентность типов. Поэтому в следующем примере переменные pb и pb1 считаются принадлежащими к разным типам:

var pb: integer;

pb1: integer;

begin

pb:=pb1; // ошибка компиляции!

if pb<>pb1 then ; // ошибка компиляции!

...

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

type pinteger=integer;

var pb: pinteger;

pb1: pinteger;

procedure pr(p: pinteger);

begin

...

end;

...

pb:=pb1; // верно

if pb<>pb1 then ; // верно

pr(pb); // верно

К типизированным указателям применима операция разыменовыния : запись pa означает «объект, на который указывает pa» (под объектом здесь понимается область памяти, выделенная программой и трактуемая как переменная или константа определенного типа). В частности, если pa хранит адрес переменной a, то разыменованный указатель pa и имя переменной a эквивалентны, поскольку ссылаются на один объект. Вообще, ссылка на объект – это выражение, однозначно определяющее этот объект. В нашем примере имя переменной a и выражение pa являются ссылками на один и тот же объект в памяти.

Нулевой указатель и указатель типа pointer разыменовывать нельзя. При разыменовании переменной-указателя, имеющей нулевое значение, произойдет ошибка времени выполнения, разыменование же указателя pointer приведет к ошибке компиляции.

Если типизированный указатель хранит адрес записи или массива, то в Delphi Pascal при обращении через указатель к полю записи или элементу массива операцию разыменования можно не использовать. Например:

type IArr = array [1..100] of integer;

Rec = record i,j: real; end;

var a: IArr; pa: IArr;

r: Rec; pr: Rec;

begin

pa:=@a;

pr:=@r;

pa[1]:=2; // вместо pa[1]:=2

pr.i:=3; // вместо pr.i:=3

end.