Где мы можем использовать указатели на функции в C, что используется для указателей на функции - PullRequest
3 голосов
/ 02 сентября 2011

Совсем недавно меня спросили в интервью: где мы можем использовать функциональные указатели в C? И какой указатель на функцию возвращает. Я сказал, что с помощью мы можем вызывать функции с помощью указателя на функцию, затем он попросил привести пример, но я не смог удовлетворить его еще одним примером. Затем он спросил меня, что функция возвращает указатель. Я сказал ему, что это зависит от объявления указателей на функции.

Но я действительно хотел бы знать, как использовать указатель на функцию в C.

Ответы [ 4 ]

14 голосов
/ 02 сентября 2011

Я думаю, классическим примером в C является qsort . Цитирую оттуда (и я действительно знаю, что это http://www.cplusplus.com,, так что не очень хороший сайт, но, похоже, это правильно)

void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );

Функция, которая сравнивает два элемента. Функция должна следовать этому прототипу:

int comparator ( const void * elem1, const void * elem2 ); 

Функция должна принимать два параметра, которые являются указателями на элементы, приведенные к типу как void *. Эти параметры должны быть возвращены к какому-либо типу данных и сопоставлены.

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


Другим «классическим» примером является калькулятор (например, см. это , это C ++, но то же самое в C).

У вас есть четыре математические функции, например

float Plus    (float a, float b) { return a+b; }
float Minus   (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide  (float a, float b) { return a/b; }

каким-то образом вы выбираете операцию

/* Here there should be an if or a switch/case that selects the right operation */
float (*ptrFunc)(float, float) = Plus;

и вы можете вызвать его позже (по какой-то причине вы не хотите вызывать его напрямую в if/switch, возможно, потому что вы хотите сделать другие "вещи", "общие" для всех операций, такие как ведение журнала или распечатать результат)

float result = ptrFunc(1.0f, 2.0f);

Еще две вещи, для которых вы можете использовать указатели функций, это обратные вызовы (как написано vine'th) и виртуальные функции «бедняков» (вы помещаете их в struct и когда вы создаете struct (вы знаете, как использование конструктора «бедняги», но это C, поэтому мы будем называть его инициализатором), вы сохраняете там, какие функции будут использоваться этим struct).

4 голосов
/ 02 сентября 2011

Если у вас нет наследования / классов и т. Д., Вы можете эмулировать это с помощью C. Например, вызывайте разные функции в зависимости от некоторых условий.

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

И да, вы правы относительно возвращаемого значения. Это зависит от определения.

2 голосов
/ 02 сентября 2011

Указатели функций используются в асинхронных уведомлениях, например, общая парадигма состоит в передаче указателя функции и данных обратного вызова, которые будут вызываться библиотекой. Вы можете увидеть пример в glib mainloop ; В C ++ STL вы можете взглянуть на широко используемые функторы , а указатель на функцию - это функтор.

0 голосов
/ 02 сентября 2011

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

Рассмотрим qsort ().Это общий алгоритм сортировки.Использование указателя функции для сравнения элементов позволяет пользователю настраивать qsort () в соответствии с их конкретным типом данных.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...