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

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

Передача параметров в функцию - student2.ru Передача параметров в функцию - student2.ru Передача параметров в функцию - student2.ru Передача параметров в функцию - student2.ru 2

       
 
X
 
Y

       
    Передача параметров в функцию - student2.ru
  Передача параметров в функцию - student2.ru
 

1 3

 
  Передача параметров в функцию - student2.ru

Рис.5.1

Для обмена двумя значениями вводится временная переменная temp, согласованная по типу с переменными x и y.

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

temp = x;

x = y;

y = temp;

Рассмотрим программу, реализующую обмен конкретными значениями.

Пример 5.2. Программа обмен

#include <stdio.h>

void obmen( int, int); // Прототип функции

void main ( void)

{

int x = 5, int y = 20;

printf (“ x = %d y = %d”, x, y);

obmen ( x, y); // Вызов функции

printf (“После обмена : x = %d y = %d”, x, y);

}

// Описание функци

void obmen( int a, int b);

{

int temp;

temp = a;

a = b;

b = temp;

}

На входе программы a и b получили значения x и y, но на выход результат не передавался и значения внешних переменных x и y не изменились.

Результат работы программы будет выглядеть следующим образом:

x = 5 y = 20.

После обмена значениями: x = 5 y = 20, т.е. значения переменных не поменялись местами. Это произошло потому, что по правилам языка Си параметры функции являются параметрами - значениями. Это означает, что в момент обращения к функции, ей в качестве фактических параметров передаются не сами переменные, а их копии в виде значений, которые они имеют в данный момент.

Изменение значений локальных переменных a и b никак не сказывается на значениях x и y. Это совершенно различные переменные.

Каким же образом все - таки поменять значения переменных x и y в программе? Для этого следует использовать указатели. Почему? Потому что указатель – это адрес переменной, следовательно, используя указатель можно осуществлять доступ к самой переменной. Значение указателя и в вызывающей программе и в функции, которой это значение передано, указывает на одну и ту же переменную.

Как будет выглядеть правильная программа? Запишем ее.

Пример 5.3.

# include <stdio.h>

void obmen (int*, int*);

void main(void)

{

int x = 5, y = 20;

printf (…);

obmen (&x, &y); //адрес x, y = указателю на a и b.

printf (“ x = %d y = %d”, x, y);

}

void obmen (int*a, int*b)

{

int temp;

temp = *a; //разадресация, т.е. берется значение по адресу

*a = *b;

*b = temp;

}

Теперь программа будет работать правильно.

Декларация void obmen (int*, int*)

говорит о том, что в качестве аргументов в функцию obmen () следует передать указатели (адреса). Вот почему при вызове функции в качестве фактических параметров используют &x и &y, т.е.:

obmen (&x, &y).

Ссылочные переменные

Как мы видели в примере 5.3, при передаче в функцию указателей в теле функции необходимо использовать явно операцию разадресации (* адрес объекта). Это усложняет синтаксис. Чтобы исключить этот недостаток в языке Си были введены ссылки. Ccылка – это другое имя переменной (объекта). Синтаксис объявления ссылочной переменной имеет следующий вид:

Тип &имя ссылки=имя объекта;

Например:

int x = 20;

float y;

int &n = x;

float &m =y;

После таких объявлений ссылочные переменные n и m будут определять местоположение в памяти переменных x и y, т.е., если ссылке присваивается значение, то и переменная получит тоже значение.

Из примеров видно, что при объявлении ссылочной переменной она обязательно должна быть проинициализирована, так как в противном случае неясно на какой объект будет производиться ссылка.. При обращении к ссылочным переменным нет необходимости в операции снятия ссылки, т. е. переменные n и m будут обрабатываться как “нормальные” переменные типов int и float.

Запишем теперь программу, изменяющую значения переменных с использованием ссылочных переменных:

Пример: 5.4

# include<stdio.h>

void obmen(int &, int &);

void main (void)

{

int x = 5, y = 20;

printf(“x = %d y = %d \n”, x, y);

obmen(x, y);

printf(“x = %d y= %d \n”, x, y);

void obmen(int &a, int &b);

{

int temp;

temp = a;

a = b;

b = temp;

}

Из примера 5.4 видно, что синтаксис при использовании ссылок более удобен.

Рекурсивные вызовы функций

Любая функция может быть вызвана рекурсивно, т. е. она может вызвать саму себя. Классический пример рекурсии – это вычисление факториала числа n! =1*2*3…*n. Пример рекурсивной функции, вычисляющей значение факториала для n> 0:

fact (int n) // Название функции

{

int a;

if (n= = 1) return 1;

a = fact (n – 1)*n;

return a;

}

Массивы и функции

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

int func(int mas[] [N], int n, int m);

При таком описании функции компилятору сообщается на сколько строк следует разбить передаваемый массив - параметр.

Вызов такой функции должен иметь следующий вид:

var = func(mas, n, m);

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

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

Пример:5.5 /* Программа работы с матрицей */

#include<stdio.h>

#include<conio.h>

#define N 5 // Задание размера матрицы в виде макроса

void input (int mas[] [N], int, int); /* функция ввода матрицы */

int making (int mas[] [N], int, int); /* функция определения максимального элемента */

void main (void)

{

int m, n ;

int a[N][N] ;

int max ;

clrscr() ;

printf (" Введите размер исходной матрицы \n ");

printf (" Число строк = ");

scanf("%d", &m);

printf (" Число столбцов = ");

scanf ("%d", &n);

input(a, m, n); // Выэов функции

max = making(a, m, n);

printf("Значение максимального элемента матрицы равно %d \n", max);

getch();

}

/* Функция осуществляет ввод матрицы

заданного размера */

void input (int a[] [N], int m, int n)

{

int i, j;

for (i = 0;i < m; i++)

for (j = 0; j <n; j++)

{

printf (" Введите A(%d,%d) элемент матрицы : '', i+1, j+1);

scanf ("%d", &a[i] [j]);

}

}

/* Функция вычисляет максимальный элемент матрицы заданного размера */

int making (int a[] [N], int m, int n)

{

int max = a[0] [0] ;

int i, j ;

for (i=0 ; i<m; i++)

for (j=0 ; j<n ; j++)

if (max <a[i] [j] )

max = a[i] [j] ;

return max ;

}

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

void input (int mas[N] , int) ;

int making(int mas[N] , int) ;

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

Наши рекомендации