Использование указателей при вызове процедур
Предположим, что формальный параметр 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);