double arrow

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



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

void MyFun(int a)

{

  a=100;

}

void main()

{

  int a=10;

  MyFun(a);

  printf("a=%d", a); // Будет напечатано a=10

}

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

  Оперативная память
….. ….. …..   Стек
Переменная a=10
Копия a=100

 


Примечание. Стек(англ. stack — стопка) — структура данных, в которой доступ к элементам организован по принципу LIFO (англ. last in — first out, «последним пришёл — первым вышел»). В оперативной памяти выделяется специальный сегмент стека для временного хранения данных, который работает по такому же принципу.




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

Такой механизм передачи параметров в функцию называется передача параметров по значению (в стек копируется значение параметра).

 


Передача параметров в функции по указателю (по ссылке)

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

#include <stdio.h>

void MyFun(int* pa)

{

  *pa=100;

}

void main()

{

  int a=10;

  MyFun(&a);

  printf("a=%d", a); // Будет напечатано a=100

}

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



  Оперативная память
….. ….. …..   Стек
Переменная a=10, 100
pa - адрес a
*pa=100

 

 


Такой механизм передача параметров называется передача параметров по указателю.

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

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

В языке Си++ появился новый тип – ссылки. В некоторых случаях их удобно использовать вместо указателей в качестве параметров функции, так как ссылка, по сути, является указателем, но к ней не надо применять операцию обращения по адресу («*»). В представленном ниже примере функция также меняет значение параметра.

#include <stdio.h>

void MyFun(int& la) // Параметр функции - ссылка

{

  la=100; // Не нужно применять операцию – обращение по адресу

}

void main()

{

  int a=10;

  MyFun(a); // При вызове не нужно получать адрес

  printf("a=%d", a); // Будет напечатано a=100

}

 


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

Передача в функцию массивов, не являющихся строками

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

Ниже представлен пример функции, которая считает сумму элементов массива.

#include <stdio.h>

int GetSum(int *p, int n) // p - указатель на массив, n - число элементов

{

  int sum=0; // Начальное значение суммы

  int i;

  for(i=0; i<n; i++) sum+=p[i]; // Прибавляем к сумме элементы массива

  return sum;

 

}

void main()

{

  int M[]={1, 2, 3, 4, 5};

  int sum=GetSum(M, 5); // Вызов функции

  printf("sum=%d", sum); // sum=15

}

 

При передаче массивов в функцию разрешена другая форма записи заголовка функции:

int GetSum(int p[], int n)

 

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

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

#include <stdio.h>

int GetLen(char *str) // str - указатель на строку

{

  int len;

  for(len=0; str[len]; len++); // Пока не встретится 0 увеличиваем индекс len

  return len;

}

void main()

{

  char S[]="Hello world";

  printf("len=%d", GetLen(S)); // Будет напечатано len=11

}

 



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