Передача массивов в качестве параметров

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

 

#include <iostream.h>

int sum(const int* mas, const int n);

int const n = 10;

int main(){

int marks[n] = {3, 4, 5, 4, 4};

cout << "Сумма элементов массива: " << sim(marks, n);

return 0;

}

int sum(const int* mas, const int n){

// варианты: int sum(int mas[], int n)

// или int sum(int mas[n], int n)

// (величина n должна быть константой)

int s = 0;

for (int i = 0; i<n; i++) s += mas[i];

return s;

}

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

В этом случае память выделяется в два этапа: сначала под столбец указателей на строки матрицы, а затем в цикле под каждую строку. Освобождение памяти должно выполняться в обратном порядке.

Передача имен функций в качестве параметров

Функцию можно вызвать через указатель на нее. Для этого объявляется указатель соответствующего типа и ему с помощью операции взятия адреса присваивается адрес функции:

 

void f(int a){/*...*/} // определение функции

void (*pf)(int); // указатель на функцию

...

pf = &f; // указателю присваивается адрес функции

// (можно было написать pf = f;)

pf(10); // функция f вызывается через указатель pf;

// (можно написать (*pf)(10))

 

Для того чтобы сделать программу легко читаемой, при описании указателей на функции используют переименование типов (typedef). Можно объявлять массивы указателей на функции (это может быть полезно, например, при реализации меню):

 

// Описание типа РF как указателя

// на функцию с одним параметром типа int::

typedef void (*PF)(int);

 

// Описание и инициализация массива указателей:

PF menu[] = {&new, &open, &save};

menu[1](10); // Вызов функции open

 

Здесь new, open и save — имена функций, которые должны быть объявлены ранее.

Указатели на функции передаются в подпрограмму таким же образом, как и параметры других типов:

 

#include <iostream.h>

typedef void (*PF)(int);

void f1(PF pf){

// функция f1 получает в качестве параметра указатель типа PF

pf(5); // вызов функции, переданной через указатель

}

void f(int i){cout << i;}

 

int main(){

f1(f);

return 0;

}

 

Тип указателя и тип функции, которая вызывается посредством этого указателя, должны совпадать в точности.

Параметры со значениями по умолчанию

Чтобы упростить вызов функции, в ее заголовке можно указать значения пара­метров по умолчанию. Эти параметры должны быть последними в списке и мо­гут опускаться при вызове функции. Если при вызове параметр опущен, должны быть опущены и все параметры, стоящие за ним. В качестве значений параметров по умолчанию могут использоваться константы, глобальные переменные и выра­жения:

 

int f(int a, int b = 0);

void f1(int, int = 100, char * = 0); /* обратите внимание на пробел между * и = (без него получилась бы операция сложного присваивания *=) */

void err(int errValue = errno); // errno - глобальная переменная

f(100); f(a, 1); // варианты вызова функции f

f1(a); f1(a, 10); f1(a, 10, "Vasia");// варианты вызова функции f1

f1(a,, "Vasia"); // неверно!


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: