Используя определение функции - ее возвращаемый тип и типы параметров мы можем описать тип функций. Для этого применяется оператор typedef:
typedef возвращаемый_тип (название)(типы_параметров);
Определение типа функции упрощает применение указателей на функции. Возьмем простейший пример:
#include <stdio.h> typedef void (message)(void); void hello() { printf("Hello, World \n"); } void goodbye() { printf("Good Bye, World \n");} int main(void) { message* mes1 = &hello; // указатель указывает на функцию hello message* mes2 = &goodbye; // указатель указывает на функцию goodbye mes1(); // Hello, World mes2(); // Good Bye, World return 0; }
В данном случае определяется тип message, который фактически будет выступать в качестве для псевдонима для функции, которая принимает не принимает никаких параметров и ничего не возвращает
(возвращаемый тип - void
).
typedef void (message)(void);
Далее мы можем использовать этот тип для определения переменных или параметров, которые представляют функцию без параметров и возвращаемого результата. Так, для теста в программе определены две такие функции - hello() и goodbye(). Соответственно мы можем определить указатель на тип message и присвоить ему адрес на одну из этих функций:
message* mes1 = &hello; // указатель указывает на функцию hello
В данном случае переменная mes1 представляет указатель на функцию типа message и хранит адрес функции hello. Далее мы можем вызывать переменную mes1 как стандартную функцию - в реальности будет вызываться функция, адрес которой хранится в переменной mes1:
mes1(); // Hello, World
Консольный вывод:
Hello, World Good Bye, World
Рассмотрим другой пример - с параметрами и возвращаемым результатом:
#include <stdio.h> typedef int (binary_op)(int, int); // определяем тип binary_op int sum(int x, int y) { return x + y;} int subtract(int x, int y) { return x - y;} int main(void) { int a = 10; int b = 5; int result; binary_op *op1 =∑ binary_op *op2 =&subtract; result = op1(a, b); printf("result = %d \n", result); // result=15 result = op2(a, b); printf("result = %d \n", result); // result=5 return 0; }
Здесь определяем тип binary_op, который будет представлять функцию, которая принимает два параметра типа int
и возвращает также значение int
.
typedef int (binary_op)(int, int); // определяем тип binary_op
Далее мы можем использовать этот тип для определения переменных, которые будут указывать на функции с соответствующими типа параметров и возвращаемым типом:
binary_op *op1 =∑
В данном случае переменная op1 представляет указатель на функцию типа binary_op, и этой переменной присваивается адрес функции sum. Далее мы можем вызывать переменную op1 как стандартную функцию передавая в нее аргументы и получая из нее результат:
result = op1(a, b);
Тип функции удобно применять, когда нам необходимо указать определение функции, однако полная запись выглядит несколько громоздкой. Например, мы можем использовать тип функции при указании прототипа функции:
#include <stdio.h> typedef int (binary_op)(int, int); binary_op sum; // прототип функции sum int main(void) { binary_op* op1 = ∑ printf("result = %d \n", op1(10,5)); // result=15 return 0; } int sum(int x, int y) { return x + y;}
Подобным образом можно определить массив указателей на функции:
#include <stdio.h> typedef int (binary_op)(int, int); int sum(int x, int y) { return x + y;} int subtract(int x, int y) { return x - y;} int multiply(int x, int y) { return x * y;} int main(void) { binary_op* operations[] = {&sum, &subtract, &multiply}; // массив функций binary_op printf("result = %d \n", operations[0](10,5)); // result=15 printf("result = %d \n", operations[1](10,5)); // result=5 printf("result = %d \n", operations[2](10,5)); // result=50 return 0; }
Тип функции можно определить как указатель. Например:
typedef int (*binary_op)(int, int);
Но стоит понимать, что в этом случае binary_op уже будет представлять указатель:
#include <stdio.h> typedef int (*binary_op)(int, int); int sum(int x, int y) { return x + y;} int main(void) { binary_op op1 = ∑ // op1 уже изначально представляет указатель printf("result = %d \n", op1(10,5)); // result=15 return 0; }