08 мая 2012

#5 Массивы как параметры функций

... или «— Хотел бы я сделать ещё запутаннее, да не смог»

Рассмотрим быстренько эту тему.
Когда массивы передаются в функцию как параметр, передаётся указатель на первый элемент массива. Это называется   разложением (decay)  .

Напишем функцию
void func(int _array[7]);
Из объявления следует, что она принимает указатель на тип int. Не более того. В эту функцию можно передать как простой указатель, так и массив другой размерности — пусть вас не смущает число 7. Следовательно, рассчитать количество элементов в массиве можно следующим образом (определяем функцию func):
void func(int _array[7]) {
  int iSize = sizeof(_array) / sizeof(_array[0]);
}

А что если это не массив вовсе? А мы просто получили указатель на целочисленный тип? Ведь сигнатуру функции можно переписать так:
void func(int* _array);
и её смысл останется абсолютно таким же.

...

Однако, принято, если ожидается последовательность элементов, объявлять параметр следующим образом:
void func(int _array[]);

Она по-прежнему ожидает int*, но приятнее для чтения. Да и клиенту функции как-бы говорит: «Я жду массив. Если пришлёшь мне что-нибудь другое, я за последствия не отвечаю.»

Если же требуется, чтобы функция принимала массивы с точным количеством элементов, можно прибегнуть к ссылке:
void func_ref(int (&_array)[7]);
Но это сработает только если мы будем передавать туда объект массива. А указатель на первый элемент массива не «прокатит»:
int* piArray = new int[MAX];
func_ref(piArray);   // Это не сработает.

Но обычно такие функции принимают второй целочисленный параметр, указывающий на количество элементов в передаваемом массиве:
void func(int _array[], int size);

В случае с многомерными массивами вторые (и последующие) границы не разлагаются, так как невозможно было бы применять арифметику к указателям. Многомерный массив
int array[3][5];
представляет из себя массив массивов.

void func(int (*_array)[5]); // Параметр этой функции — указатель 
                             // на массив из 5 элементов типа int.
void func(int _array[][5]);  // То же самое. Только понятнее.


Об этом говорят специалисты: