Передача одномерного массива в функцию
Под передачей массива в функцию будем понимать использование имени массива в качестве фактического параметра функции, например, 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.
Объяснить результаты работы программы.