Типизированные указатели

Декабрь 4, 2010 / Автор AlexR / Рубрики Учебник по паскалю / Комментировать

Краткие теоретические сведения находятся в пункте «Указатели: Общие сведения»

Указатель – это тип. Переменную типа указатель также называют указатель.

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

Объявление типизированного указателя:

var

<имя указателя>:=^<тип>;

Пример:

var
    a: integer;
    pI: ^integer;

Данная запись читается так: pI – указатель на integer (целочисленную переменную).

Для того чтобы указать pI на a следует применить операцию взятия адреса @, а для того, чтобы получить значение переменной через указатель применяют операцию разыменования ^:

begin
    pI:=@a; //Присвоили указателю адрес переменной a
    pI^:=5; //Записали по указателю значение 5, при этом a стало равно 5
    writeln ('Значение переменной через указатель:', pI^);
end.

Если при выводе значения после pI не поставить операцию разыменования, то на экран выведется адрес переменной a.

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

С самими указателями (без операции разыменования) можно делать практически все операции, кроме умножения и деления. Что происходит, например, когда к указателю прибавить единицу?

begin
    pI:=@a; //Присвоили указателю адрес переменной a
    pI^:=5; //Записали по указателю значение 5, при этом a стало равно 5
    writeln ('Значение переменной через указатель:', pI^);
    writeln ('Адрес, который записан в указателе:', pI);
    pI:=pI+1;
    writeln ('Новый адрес, который записан в указателе:', pI);
end.

Если значение адреса в pI было, к примеру: $0A652F04, то после увеличения на единицу, казалось бы, должен стать $0A652F05. Но не тут то было, вывелось $0A652F08.

Все просто: тип нашего указателя: integer — можно посмотреть в таблице типов, сколько занимает данный тип места в памяти: ровно 4 байта — поэтому адрес увеличился на 4. Другими словами операции сложения и вычитания делают со значениями указателей следующее: здесь целое число (у нас оно равно 1) означает количество ячеек указуемого типа, а знак операции — куда сдвигаться (в нашем случае мы сдвигаемся в памяти “вправо”).

Примечание: все адреса хранятся в шестнадцатеричной системе счисления

Примечание: арифметические действия с указателем нельзя выполнять для указателей на пользовательские типы. Видимо, компилятор паскаля запрещает это делать.

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

Приведу пример:

program func;
var
    a: integer;
    p:^integer;

function square (p:^integer):integer; //Здесь говорят так, что значение формального параметра передается по указателю
begin
    p^:=p^*p^; //Локальная переменная a в вызывающей функции будет изменяться
end;

begin
    a:=10;
    p:=@a;
    square(p); //Поэтому здесь возвращаемое значение функции можно ни к чему не присваивать, так как оно уже записано в a
    writeln (a); //Выведется 100
end.

Вернуться к оглавлению

Комментарии закрыты.