Создание передачи по указателю
Хотя, как правило, передача параметров происходит по значению, можно передать параметр по ссылке. Поскольку в данном случае происходит передача адреса аргумента, возможно изменение значения аргумента, находящегося вне функции.
Указатели передаются в функции, как и обычные значения. Конечно, необходимо объявлять параметр типа указатель. Пример – функция, меняющая значение двух целочисленных аргументов.
void swap(int *x, int *y)
{ int temp;
temp = *x;
*x = *y;
*y = temp;
}
Оператор * используется для доступа к переменным, на которые указывают операнды. Важно помнить, что любая функция, использующая указатели на параметры должна вызываться с адресами аргументов. Следующая программа демонстрирует правильный способ вызова swap():
#include <stdio.h>
void swap(int *x, int *y);
int main(void)
{
int x, y;
x = 10;
y = 20;
swap(&x, &y);
printf(“%d %d”, x, y);
return 0;
}
В данном примере переменной х присваивается значение 10, а переменной у – 20. Затем вызывается swap() с адресами х и у. Унарный оператор & используется для получения адресов переменных. Поэтому в функцию swap() передаются адреса х и у, а не их значения.
Лекция 8.
План
Указатели на функции
Структуры
Доступ к членам структуры
Присваивание структур
Массивы структур
Указатели на функции
Хотя функция – это не переменная, она имеет физическое положение в памяти, которое может быть присвоено указателю. Адрес, присвоенный указателю, является входной точкой в функцию. Указатель может использоваться вместо имени функции. Он также позволяет передавать функции как обычные аргументы в другие функции.
Адрес функции получается при использовании имени функции без скобок и аргументов. Пример:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.1415
double del2(double a, double b, double eps, double (*f)(double));
int main(void)
{
double (*p)(double);
p = sin;
double a = -PI/2, b = PI/2, eps = 0.0001;
printf("Root = %lf\n", del2(a,b,eps,p));
printf("Root = %lf\n", del2(a,b,eps,sin));
return 0;
}
double del2(double a, double b, double eps, double (*f)(double))
{
if(b<a) {
puts("Left bigger than right");
exit(0);
}
if(eps <= 0) {
puts("Eps <= 0");
exit(0);
}
if(f(a) == 0) return a;
if(f(b) == 0) return b;
while(b-a >= eps) {
double x=(a+b)/2;
if(f(a)*f(x) < 0.) a=x;
else if(f(x) == 0.) return x;
else b=x;
}
return (a+b)/2;
}
Когда вызывается del2(), ей передаются числа с плавающей точкой двойной точности и один указатель на функцию. Скобки вокруг *f необходимы для правильной интерпретации компилятором данного выражения.
При объявлении указателя на функцию можно использовать прототип, оставив имена параметров пустыми.
Рассмотрим работу функции sin() в функции del2(). Оператор
if(f(a) == 0) return a;
осуществляет вызов функции, в данном случае sin(), с помощью f, который указывает на данную функцию. Вызов происходит с аргументом a.
Бывают моменты, когда выгодно передавать функции в процедуры или хранить массивы функций. Пример:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
void enter(void), del(void); void review(void), quit(void);
int menu(void);
void (*options[])(void) = {
enter,
del,
review,
quit
};
int main(void)
{
int i;
i = menu();
(*options[i])();
getchar();
return 0;
}
int menu(void)
{
char ch;
do {
printf("1. Enter\n");
printf("2. Delete\n");
printf("3. Review\n");
printf("4. Quit\n");
printf("Select a number:");
ch = getche();
printf("\n");
}while(!strchr("1234", ch));
return ch-49;
}
void enter(void)
{ printf("In enter.");}
void del(void)
{ printf("In del.");}
void review(void)
{ printf("In review.");}
void quit(void)
{
printf("In quit.");
exit(0);
}