Организация и функционирование компьютеров
bf1271d8

Использование указателей при вызове процедур


Предположим, что формальный параметр z процедуры p

является указателем  на значение определенного типа (например, целого). Тогда при обращении к процедуре  во внутреннюю переменную скопируется адрес, а само значение по данному адресу не будет затронуто. Если в процедуре встретится присваивание  вида z^ := 7, то по адресу указателя заносится число 7. При выходе из процедуры это значение останется, то есть переменная по этому адресу получит новое значение. Например, после вызова p(@n) переменная n

примет значение 7. Эффект будет таким же, как если бы задать параметр обычным целым числом, но описать его выходным (с ключевым словом var) и обратиться к процедуре оператором p(n).

Однако использование указателя имеет свои преимущества. Оно позволяет обойти стандартное ограничение Паскаля на строгое соответствие типов формального и фактического параметров вызова процедуры. Особенно это касается соответствия длин массивов. Дело в том, что определение указателя некоторого типа требует выделения памяти для хранения адреса, но не требует выделения памяти для хранения значения этого типа. Оператор вида p:=@x всего лишь совмещает значение, обозначаемое как p^, с уже существующей переменной x. Пусть имеется указатель p на массив некоторой длины n и массив a

меньшей длины k, а типы элементов массивов одинаковые. Если теперь присвоить p^:=@a, то при обращении к элементам вида p^[m], где m>k, фактически произойдет обращение к памяти, не принадлежащей массиву a, что неправильно. Но если программно следить за тем, чтобы индекс в выражении p^[m]

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

function find_integer (

    x: integer;   {Значение для поска}

     p: pointer;  {Массив для поиска}

     n: integer)  {Длина массива}

        : integer;      {Возвращает номер совпавшего элемента или 0 в случае неудачи}

type  ar: array [1..30000] of integer;

var



    k: integer;

    p1: ^ar;

begin

    find_integer := 0;

    p1 := p;

    for ki:=1 to  n  do

        if  p1^[k]=x  then

            begin

                find_integer := k;

                break

            end

end;

Обратиться к данной функции можно следующим образом:

var a: array [1..20] of

integer;

...

i := find_integer (23,@a,20);



Содержание раздела