Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab_C-08.doc
Скачиваний:
2
Добавлен:
21.11.2019
Размер:
81.92 Кб
Скачать

Рубанчик В.Б.

Лабораторная работа "Передача массивов в функции"

5/5

Лабораторная работа

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

Цель работы: Изучить особенности использования массивов как аргументов функций

Имена массивов и указатели

В Си разница между именем одномерного массива и указателем на тип элементов этого массива проявляется в двух случаях:

1. Использование имени массива в роли указателя.

Имена массивов трактуются компилятором как адреса, а именованные адреса в Си называются указателями.

Обычно под указателем понимают переменную, т.е. объект, который при выполнении программы может изменить свое значения. Для изменения значения переменная должна быть помещена в левую часть оператора присваивания (использоваться как l-value).

Но имена массивов — это особый тип указателей. Они обозначают адрес, который меняться не может (указатель-константа). Поэтому имена массивов (без индексов) могут появляться только в правых частях выражений (использоваться только, как r-value)

Пример 1.

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

int arr[12], *pa=arr;

arr++ ; /* Ошибка! Объяснить, почему? */

pa++; /* Правильно */

2. Использование имени массива для вычисления размер объекта.

Результатом применения операции sizeof к имени массива будет размер отведенной массиву памяти (в байтах).

Если применить операцию к однотипному с массивом указателю (pa), то будет вычислен размер указателя, т.е. объем памяти, используемый в программе для хранения адреса.

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

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]