При использовании в качестве параметра массива в функцию передается указатель на его первый элемент, иными словами, массив всегда передается по адресу. При этом информация о количестве элементов массива теряется, и следует передавать его размерность через отдельный параметр (в случае массива символов, то есть строки, ее фактическую длину можно определить по положению нуль-символа):
#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"); // неверно!