русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Указатели и их объявление


Дата добавления: 2014-11-28; просмотров: 599; Нарушение авторских прав


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

Чтобы связать ссылочный тип с определенным типом данных, используется символ ^, помещаемый перед именем типа. Например, имеется тип массив:

Type

A = Array[1..100] of integer;

Тип указателя на такой объект:

Type

tA = ^A;

Переменные ссылочного типа могут определяться как статические, при этом по общим правилам объявления переменных возможна запись с явным и неявным определением ссылочного типа.

Type

A = Array[1..100] of integer; {Тип массив из 100 целых чисел}

tA = ^A; {Тип указатель на тип А}

Var

B : tA; {Указатель на тип А}

C : ^A; {Указатель на тип А}

Для получения данных, соответствующих указателю, символ "^" приводится после имени указателя. Действия с элементами массива типа А могут быть описаны через действия над указателями В и С.

B^[i] := i; {i-му элементу массива, на который указывает В, присвоить значение i}

C^[i] := B^[i]; {i-му элементу массива, на который указывает С, присвоить значение i-го элемента массива, на который указывает В}

После выполнения этого кода i-е элементы массивов, на которые указывают В и С, будут равны.

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

Разберем простой пример, обратив еще раз внимание на синтаксис:

Var

P : ^integer; {Указатель на целое}

P^ – переменная целого типа, на которую ссылается Р, она может стоять как в левой, так и в правой части выражений:

P^ :=16;



x := x+P^;

Первый оператор присваивает целочисленной переменной, на которую ссылается Р, значение 16, второй прибавляет к значению переменной х значение 16, второй прибавляет к значению переменной х значение 16. Аналогично определяются и используются указатели на переменные любого типа, в том числе и определенного пользователем.

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

Схематически можно представить себе указатель так:

адрес

Указательная переменная Р может быть в трех состояниях.

1. Содержать адрес какой-либо переменной, память под которую уже выделена.

адрес

2. Содержать специальный пустой адрес Nil.

3. Находиться в неопределенном состоянии.

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

Схематически различия между состоянием Nil и неопределенным состоянием можно изобразить так:

Использование имени указателя в программе означает обращение к адресу ячейки памяти, на которую он указывает. Чтобы обратиться к содержимому ячейки, на которую указывает указатель, требуется после его идентификатора поставить символ ^. Эта операция еще называется разыменованием.

Для представления указателя на строку с завершающим нулем в Паскале имеется предопределенный тип PChar. В модуле System этот тип описывается следующим образом:

Type

PChar = ^char;

Паскаль поддерживает набор расширенных правил, позволяющих работать со строками с завершающим нулем, используя тип PChar.

Иногда связи между ссылкой и переменной не существует по смыслу задачи, в этом случае с указателем нельзя связать никакой объект, а ссылка должна быть пустой. Зарезервированное слово Nil обозначает константу со значением указателя, который ни на что не указывает. После присвоения

P := Nil;

указатель не будет указывать ни на какой объект. Значение Nil совместимо с любым ссылочным типом.

Операции "=" и "<>" могут использоваться для сравнения операндов типа указатель. Два указателя равны только в том случае, если они ссылаются на один и тот же объект.

Занятие 2. Присвоение значений указателю. Оператор @ с переменной. Оператор @ с параметром процедуры, переданным по значению. Оператор @ с параметром процедуры, переданным по ссылке.

Переменной-указателю можно присвоисть значение другого указателя того же типа. В языке существует универсальный тип указателя, его имя – pointer. Используя тип pointer как промежуточный, можно присвоить значение одного указателя другому и при несовпадении их типов.

Для инициализации указателей в Паскале предусмотрены специальные процедуры и функции.

Переменной-указателю можно присвоить значение с помощью процедуры new, операции @ или функции Ptr.

Процедура new отводит блок памяти в области для динамических переменных и сохраняет адрес этого блока в указателе.

Операция @ ориентирует переменную-указатель на область памяти, содержащую уже существующую переменную. Ее можно применять к статическим переменным, динамическим переменным, процедурам и функциям.

Функция Ptr ориетирует переменную-указатель на определенный адрес в памяти. Тип результата – указатель того же типа, что и Nil, т.е. он может быть назначен любой переменной-указателю.

@ – это унарный оператор. Тип значения указателя управляется через директуву компилятора $T. Если переключателшь отключен, то результатом является нетипизированный указатель, если включен, – то тип указателя соответствует типу объекта. Если оператор @ применяется к процедуре, функции или методу, то результатом всегда будет указатель типа pointer, независимо от состояния опции $T.

Оператор @ с переменной

Использование @ с обычной переменной (не параметром процедуры) несложно.

Например, можно задать декларацию

Type

A = Array [0..99] of char; {Тип массива символов}

Var

X : Array [0..49] of integer; {Массив целых чисел}

pA : ^A; {Указатель на массив символов}

Объявлены переменные двух разных типов: массива целых из 50 элементов и ссылочного на тип А (массив из 100 символов). Чтобы указатель рА указывал на массив Х, надо присвоить ему адрес Х:

рА := @Х; {Указатель на массив целых чисел}

Теперь pA^ ссылается на массив целых, но по своей природе он указатель на массив символов, поэтому при обращении pA^[i] мы получаем содержимое отдельных байтов массива Х в символьной форме.

Пример. Компонентам массива целых присваиваются сдвинутые на 65 значения индекса, печатается массив целых. Переменной-указателю на символьный массив присваивается адрес массива целых. Снова распечатывается массив, но по адресам значений. Вместо последовательности чисел будет напечатана последовательность ASCII символов от А до z с пробелами.

Program ReInterpretation;

{Интерпретация массива целых чисел как массива из символов}

Uses

Crt;

Type

A = Array [0..99] of char; {Тип A – массив 100 символов}

Var

X : Array [0..49] of integer; {Массив целых чисел}

pA : ^A; {Указатель на массив символов}

i : integer;

Begin

ClrScr;

for i := 0 to 49 do

begin

X[i] := 65+i {65 – код буквы А}

write(X[i], ' '); {Печать чисел}

End;

pA := @X; {Указателю на А присваивается адрес массива целых чисел}

writeln;

for i := 0 to 99 do

write(pA^[i],' '); {Печать символов}

End.

Попытка исполнить последний оператор до оператора pA := @X привела бы к ошибке, поскольку указатель на массив был бы не опpеделен. Массив Х имеет значения 65..114, которые не выходят за пределы младшего байта двухбайтовых элементов типа word. В старших байтах этой переменной – нули. При побайтной печати массива младшие байты выводятся как буквы алфавита, а старшие – как символ #0, который процедурой write интерпретируется как пробел.

Задание. Наберите программу, откомпилируйте ее и проверьте действие.

Оператор @ с параметром процедуры, переданным по значению

Применение @ к формальному параметру процедуры означает то же, что ссылка на фактический параметр, находящийся в стеке.

Например, пусть Х – формальный параметр процедуры, а рХ – указатель на него. Если в процедуре выполнено назначение

рХ := @Х;

то рХ^ указывает на значение Х, которое хранится в стеке.

Пример. Процедура Test присваивает локальному параметру р его адрес и выводит значение адреса в формате сегмент : смещение . Основная программа обращается к процедуре с фактическим параметром Р и выводит адрес фактического параметра.

Program FormalParam;

{Определение адреса формального параметра}

Uses

Crt;

Var

P : pointer;

Procedure Test(p: pointer);

Begin

p := @P; {Определение адреса локального параметра}

writeln ('', Seg(p^), ':', Ofs(p^));

End;

Begin

ClrScr;

Test(P); {Вызов процедуры}

writeln('', Seg(p^), ':', Ofs(p^));

End.

На экран будет выведен результат исполнения программы:

В процедуре Р=1103:16378

В основной программе Р=0:0

Задание. Наберите программу, откомпилируйте ее и проверьте действие.

Оператор @ с параметром процедуры, переданным по ссылке

Применение оператора @ к формальному переменному параметру процедуры приводит к указанию на действительный параметр процедуры (указатель берется из стека).

Например, пусть

Х – формальный переменный параметр процедуры;

а – переменная, передаваемая в процедуру как действительный параметр;

рХ – ссылочная переменная.

Если процедура, как в предыдущем примере, выполняет присвоение

pХ := @X;

то pХ – указатель на а, а pX^ – ссылка на само значение а.

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

Procedure Test(Var p:pointer);

Значение указателя в основной программе изменится и будет равно значению указателя в подпрограмме. Результат:

В процедуре Р=1119:98

В основной программе Р=1119:98

Задание. Используя одну из созданных Вами программ в теме "Процедуры и функции", модифицируйте ее, применив знания этого занятия.



<== предыдущая лекция | следующая лекция ==>
Занятие I. Динамические структуры данных. Статические и динамические переменные. Адреса. Указатели и их объявление. | Занятие 3. Список. Создание списка путем добавления элементов в конец списка. Просмотр списка


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 6.583 сек.