Массивы в процедурах и функциях языка Pascal
Обновлено: 25.04.2026
Массивы также, как и другие типы данных, можно передавать в качестве параметров в подпрограммы и возвращать их из функций. Однако определять формальные параметры, непосредственно описывая массив через базовый тип, в Паскале нельзя. Как и нельзя так делать, задавая тип возвращаемого функцией значения. Вместо этого следует определять свой тип в разделе type программы и далее использовать его.
В языке программирования Pascal раздел type предназначен для определения пользовательских типов данных и располагается до раздела var. Пользовательские типы, то есть создаваемые прикладным программистом, нередко представляют собой ограниченные версии встроенных в язык типов. После того как тип определен, его имя–идентификатор может использоваться в разделе var при создании переменных этого типа, а также в качестве параметров подпрограмм и возвращаемых функциями значений.
Рассмотрим программу, в которой целочисленный массив выводится на экран с помощью процедуры:
const N = 10; type myArray = array[1..N] of Integer; var a: myArray; i: Byte; procedure writeA(b: myArray); begin for i:=1 to N do write(b[i], ' '); writeln; end; begin randomize; for i:=1 to N do a[i] := random(100) - 50; writeA(a); end.
-40 -2 -24 42 18 -43 24 -28 48 -16
В ней мы создаем свой тип данных myArray и далее используем его при определении глобальной переменной a и параметра b процедуры. Если в случае с переменной можно было бы не использовать пользовательский тип и определить ее обычным способом, то с параметром так сделать не получится. При этом лучше, чтобы тип переменной совпадал по имени с типом параметра, и упоминание в обоих случаях myArray подчеркивает их однотипность.
Создадим в этой же программе функцию, которая заполняет массив:
... function randA(b: myArray): myArray; begin randomize; for i:=1 to N do b[i] := random(100) - 50; randA := b; end; ... begin a := randA(a); writeA(a); end.
Теперь зададимся вопросом, сколько на самом деле массивов у нас существует в программе в момент выполнения функции? Вспомним, что ранее мы говорили, что фактический параметр передается в подпрограмму по значению, и это значение присваивается формальному параметру. Поэтому, когда выполняется вызов функции randA(a) массив копируется и присваивается переменной b. Исходно массив a заполнен нулями. Но он существует, а значит, занимает память. Если представить, что массив состоит не из 10 элементов, а из тысяч, то расход памяти на второй, то есть b, будет уже существенным.
Подумайте, почему в представленном коде в момент выполнения функции на самом деле существует не два, а три однотипных массива?
Когда выполняется присваивание переменной a, ее исходный массив теряется, вместо него в нее записывается тот, что был возвращен из функции.
Мы можем вспомнить, что подпрограммы имеют доступ к глобальным переменным и, желая сэкономить память, превратить функцию в процедуру:
... procedure randA; begin randomize; for i:=1 to N do a[i] := random(100) - 50; end; ... begin randA(); writeA(a); end.
Но это лишает подпрограмму ее универсальности. Если в программе будет еще несколько массивов, которые заполняются также, то мы не сможем применить к ним нашу процедуру. Она жестко "привязана" только к переменной a.
На самом деле в языках программирования давно придумано решение на случай, когда надо изменять значение глобальной переменной, но подпрограмма не должна использовать ее имя и вообще знать о ее существовании. Решением является передача в подпрограмму параметра по ссылке, а не по значению. В этом случае переменная–параметр становится другим именем того же массива.
В языке программирования Pascal, чтобы передавать в процедуру или функцию не данные, а только ссылку на них, перед объявлением формального параметра добавляют ключевое слово var. Тогда наша процедура заполнения массива все-таки будет иметь параметр, и таким образом мы сможем передавать в нее любой массив соответствующего типа:
const N = 10; type myArray = array[1..N] of Integer; var a, e: myArray; procedure randA(var r: myArray); var i: byte; begin for i:=1 to N do r[i] := random(100) - 50; end; ... begin randomize; randA(a); randA(e); writeA(a); writeA(e); end.
В данном случае когда, например, вызывается процедура randA с фактическим параметром a, то с массивом, содержащимся в этой переменной, связывается также имя r — формальный параметр процедуры. Изменение массива через r скажутся на значении a, потому что это два имени одних и тех же данных.
Спишите программу выше, добавив в нее такое определение процедуры writeA, чтобы она выводила на экран существующий в глобальной области видимости массив, а не его копию из локальной области.
При всем этом вариант, когда функция принимает один массив, а возвращает другой, в ряде случаев имеет место быть. Представьте, что вам не надо изменять существующий массив, а необходимо создать на его основе другой. В программе ниже исходный массив передается в функцию по ссылке, однако в функции создается новый массив, который из нее возвращается и присваивается глобальной переменной b:
const N = 10; type inArr = array[1..N] of integer; mA = array[1..N] of shortInt; var a: inArr; b: mA; i: byte; function mask(var origin: inArr): mA; begin for i:=1 to N do if origin[i] > 0 then mask[i] := 1 else if origin[i] < 0 then mask[i] := -1 else mask[i] := 0; end; begin for i:=1 to N do read(a[i]); b := mask(a); for i:=1 to N do write(b[i], ' '); writeln; end.
4 5 -2 -4 0 5 -4 3 2 -1 1 1 -1 -1 0 1 -1 1 1 -1
Как в программе выше функцию превратить в процедуру, чтобы она делала то же самое?
Представьте, что в программе есть массивы разной длины, и со всеми надо выполнять однотипные действия. Однако если используются обычные массивы, передавать их в одну подпрограмму не получится. Ведь при определении нового типа мы жестко задаем его размерность. В таких случаях на помощь приходят открытые массивы, с которыми мы познакомимся на следующем уроке.
Задания для дополнительной или самостоятельной работы:
Напишите программу, в которой функция принимает минимально и максимально возможные значения массива, заполняет массив случайными числами в указанном диапазоне и возвращает этот массив в главный раздел begin-end.