Хелпикс

Главная

Контакты

Случайная статья





Возвращаемые значения, параметры, аргументы.



Возвращаемые значения, параметры, аргументы.

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

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

Пример функции, возвращающей сумму двух целых величин:

#include <iostream.h>

int sum(int a, int b); //объявление функции

int main() {

int a = 2, b = 3, c, d;

c = sum(a, b); //вызов функции

cout << "Please, enter number";

cin >> d;

cout << "\n" << sum(c, d); //вызов функции

return 0;

}

int sum(int a, int b){ //определение функции

return (a + b);

}

Локальные и глобальные переменные.

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

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

#include <iostream.h>

void f(int a){

int m = 0;

cout << "n m p\n";

while (a--){

    static int n = 0;

    int p = 0;

    cout << n++ << " " << m++ << " " << p++ << "\n";

}

}

 

int main() {

f(3);

f(2);

return 0;

}

    Статическая переменная n размещается в сегменте данных и инициализируется один раз при первом выполнении оператора, содержащего ее определение. Автоматическая переменная m инициализируется при каждом входе в блок цикла. Программа выведет на экран:

n  m p

0  0  0

1  1  0

2  2  0

n  m p

3  0  0

4  1  0

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

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

    Механизм возврата из функции в вызвавшую ее функцию реализуется оператором

    return [выражение];

    Функция может содержать несколько операторов return (это определяется потребностями алгоритма). Если функция описана как void, выражение не указывается, Оператор return можно опускать для функций типа void, если возврат из нее происходит перед закрывающей фигурной скобкой, и для функции main. Выражение указанное после return неявно преобразуется к типу, возвращаемого функцией значения и передается в точку вызова.

    int f1(){return 1;} //правильно

void f2(){return 1;} //не правильно, f2 не должна возвращать значение

double f3(){return 1;} //правильно, 1 преобразуется к double

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

int* f(){

int a = 5;

return &a; // Нельзя!!!

}

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

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

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

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

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

#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 << '\n';

return 0;

}

void f(int i, int* j, int& k){

i++; (*j)++; k++;

}

    Результат работы программы:

i   j   k

1  2  3

1  3  4

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

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

    Если требуется запретить изменение параметра внутри функции, используется модификатор const:

    int f(const char*); или

char* t(char* a, const int* b);



  

© helpiks.su При использовании или копировании материалов прямая ссылка на сайт обязательна.