logo
lab_C-08

Передача одномерного массива в функцию

Под передачей массива в функцию будем понимать использование имени массива в качестве фактического параметра функции, например, f(arr); .

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

Но, когда нужно передать в функцию массив, то копирование всего массива будет означать громоздкую операцию дублирования большого объема данных.

Поэтому авторами языка Си было решено, что при передаче массива в функцию вместо самого массива копируется только указатель на его начало. Это имеет два следствия.

а) Во-первых, формальный параметр функции, соответствующий аргументу-массиву, объявляется как указатель на тип элемента массива.

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

При передаче массивов в функции требуется учитывать следующие особенности.

а) Тип формального параметра.

Компилятор следит за тем, чтобы типы фактического и формального параметров совпадали. В примере 1 идентификатор массива arr имеет тип указателя на элемент массива (т.е. на int). Поэтому в описании функции или ее прототипа соответствующий этому массиву аргумент также должен иметь тип того же указателя:

void f(int *a){…} (1)

Здесь a — формальный параметр, который внутри функции может использоваться, как имя одномерного массива.

Вызов функции с передачей массива будет выглядеть так: f(arr);

Однако фактический параметр функции f реально не обязательно должен быть именем массива. В приведенном примере требуется только, чтобы фактический параметр имел тип int* (указателя на int).

В примере 1, наряду с массивом, был определен указатель pa (синоним имени массива arr), имеющий необходимый тип. Поэтому вызов f(pa); будет равноценным f(arr);.

б) Потеря информации о размере.

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

Когда вместо массива передается обычный указатель (pa), разговор о размере массива в обычном смысле вообще не теряет смысл. Например, может быть передан указатель не на первый, а на любой другой элемент массива.

Эти рассуждения можно обобщить на случай массивов любой размерности: при передаче массива в функцию информация о его первом (левом) размере теряется.

ЗАДАНИЕ 1 (анализ размеров объектов)

1. Массив arr типа int и указатель pa определены как в примере 1.

Написать программу, в которой с помощью операции sizeof вычисляются и выводятся на экран размеры объектов arr и pa с поясняющим текстом Massiv и Ukazatel.

Объяснить результаты работы программы.

2. В программу добавить функцию с прототипом void size_of_arg(int* a), в которой вычисляется и выводится на экран размер переменной a.

В main предусмотреть вызов функции size_of_arg два раза. Первый раз передать ей имя массива, а второй раз — указатель pa.

На экран перед результатами должен быть выведен поясняющий текст, соответственно, Peredan massiv и Peredan ukazatel.

Объяснить результаты работы программы.