Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кетков.doc
Скачиваний:
17
Добавлен:
27.09.2019
Размер:
2.22 Mб
Скачать

8.1. Параметры-значения

Формальный параметр в заголовке функции называют параметром-значением, если перед его именем указан только тип. Например, функция mid, вычисляющая среднее арифметическое двух величин, получает в качестве фактических аргументов два числовых значения определенного типа:

double mid(double x, double y)

{ return (x+y)/2.; }

В качестве фактических аргументов, соответствующих параметрам-значениям, могут быть заданы любые числовые выражения (формулы):

w1 = mid(x*cos(fi)+y*sin(fi), x*sin(fi)-y*cos(fi));

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

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

8.2. Параметры-указатели

Формальный параметр в заголовке функции называют явным параметром-указателем, если перед его именем находится символ *. Например, функция swap1, осуществляющая перестановку местами значений двух переменных, должна получить в качестве параметров адреса этих переменных, т.е. указатели на них:

void swap1(int *x,int *y) //явные параметры-указатели

{ int tmp=*x;

*x=*y; *y=tmp;

}

Кроме явных параметров-указателей в объявлении функции можно использовать и косвенные параметры-указатели, описанные с помощью механизма подстановок:

#define pint int*

...............

void swap1(pint x,pint y) //косвенные параметры указатели

{ int tmp=*x;

*x=*y; *y=tmp;

}

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

deftype int* pint;

Представим себе, что функция swap1 была бы оформлена с параметрами-значениями:

void swap1(int x,int y)

{ int tmp=x;

x=y; y=tmp;

}

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

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

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

int x=2,y=3;

swap1(&x,&y);

Рассмотрим еще один пример передачи указателя по указателю:

void swap(int **v1, int **v2)

{ int *tmp=*v1; *v1=*v2; *v2=tmp; }

К этой функции можно обратиться следующим образом:

int i=10, j=20;

int *pi=&i, *pj=&j;

swap(&pi,&pj);

после такого обращения указатели pi и pj "смотрят" на новые значения, т.к. они поменялись адресами (*p1=20, *pj=10), но сами переменные i и j свои значения не поменяли.

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

int sum_v(int *a,int n)

{ int j,s=0;

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

s += a[i];

return s;

}

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

int q[20];

..........

k1=sum_v(q,20); //суммирование всех компонент вектора

k2=sum_v(q,10); //суммирование первых 10 компонент вектора

k3=sum_v(&q[5],3); //суммирование q[5]+q[6]+q[7]

k4=sum_v(q+5,3); //суммирование q[5]+q[6]+q[7]

Не забывайте, что имя массива одновременно является и указателем на его первый элемент (т.е. q и &q[0] – это одно и то же).