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

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

Пример 2. Использование модификатора static. #include<iostream.h> voidf(inta){ intm = 0; cout<< "n m p\n"; while(a--){ static intn = 0; intp = 0; cout << n++ <<' ' << m++ << ' ' << p++ <<'\n'; } } intmain(){ f(3); f(2); return0; }

В результате выполнения этой программы на экран будет выведено следующее:

n m p
0 0 0
1 1 0
2 2 0
n m p
3 0 0
4 1 0

Такой результат выполнения программы объясняется тем, что статическая переменная n помещается в сегмент данных, а её инициализация выполняется всего один раз при первом появлении оператора, содержащего её определение. В тот же момент автоматические переменные m и p инициализируются при каждом новом входе в функцию.

Модификатор inline

Функцию можно определить как встроенную с помощью модификатора inline. В таком случае компилятор вместо обращения к функции будет помещать её код непосредственно в каждую точку вызова. Сама по себе директива inline носит, по большей степени, рекомендательный характер и выполняется компилятором по мере возможности. Важно иметь ввиду то, что использование inline-функций может повлечь за собой увеличение размера исполняемого файла программы.

Определение inline-функции всегда должно предшествовать её вызовам, иначе вместо inline-расширения компилятор выполнит обычный вызов функции.

Функции. Возвращаемое значение.

Механизм возврата из функции в вызвавшую её функции реализуется с помощью оператора return[выражение]. Функция может содержать в себе несколько операторов return и если она описана как void, выражение после этого оператора не указывается.

Также оператор return можно опускать для функции типа void, если возврат из неё происходит перед закрывающей фигурной скобкой, и для функции.

Выражение после return всегда неявно преобразуется к типу возвращаемого функцией значения и передаётся в точку вызова функции.

Пример 3. Использование return. int fl(){ return 1; // правильно } void f2(){ return 1; /* неправильно, f2 не должна возвращать значение */ } double f3(){ return 1; /* правильно, 1 преобразуется к типу double */ }

Нельзя возвращать из функции указатели на локальную переменную, так как память, выделенная под локальные переменные при входе в эту функцию, освобождается после выхода из неё.

Параметры функций.

Механизм параметров является основным способом обмена информацией между вызываемой и вызывающей функциями. Параметры, описанные в заголовке описания функции, называются формальными параметрами, а параметры, описанные в операторе вызова функции – фактическими параметрами (или аргументами).

При вызове функции последовательно выполняются следующие действия:

    1. вычисляются выражения, стоящие на месте аргументов;
    2. в стеке выделяется память под формальные параметры функции в соответствии с их типом;
    3. каждому из параметров присваивается значение соответствующего аргумента;
    4. проверяется соответствие типов и при необходимости выполняются их преобразования;
    5. при несоответствии типов выдается диагностическое сообщение

Существует два способа передачи параметров в функцию: передача по значению и по адресу.

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

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

Пример 4. Использование передачи по ссылке и по значению. #include <iostream.h> void f(int i, int* j, int &k); int main(){ int i = 1, j = 2, k = 3; cout << "i j k\n"; cout << i <<' '<< j <<' '<< k <<'\n'; f(i, &j, k); cout << i <<' '<< j <<' '<< k; return 0; } void f(int i, int* j, int &k){ i++; (*j)++; k++; }

Первый параметр (i) передается по значению, следовательно, его изменение в функции не влияет на исходное значение. Второй параметр (j) передается по адресу с помощью указателя, при этом для передачи в функцию адреса фактического параметра используется операция взятия адреса, а для получения его значения в функции требуется операция разыменования. Третий параметр (k) передается по адресу с помощью ссылки.

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

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

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

Пример 5. Передача массивов в качестве параметра. #include<iostream.h> intsum(const int* mas, const intn); int constn = 10; intmain(){ intmas[n] = {3, 4, 5, 4, 4}; cout <<"Сумма элементов массива: " <<sum(mas, n); return0; } intsum(const int* mas, const int n){ /* варианты: int sum(int mas[], int n) или int sum(int mas[n], int n) */ // (величина n должна быть константой) ints = 0; for(inti = 0; i<n; i++) s+=mas[i]; returns; }

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

 

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

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

Пример 6. Передача имён функций в качестве параметра. #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; }

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



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