2013-07-19 4 views
2

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

void populate_array(int *array, size_t arraySize, 
      int getNextValue(void)) // Note that, here I use normal function call. 
{ 
    for (size_t i=0; i<arraySize; i++) 
     array[i] = getNextValue(); 
} 

int getNextRandomValue(void) 
{ 
    return rand(); 
} 

int main(void) 
{ 
    int myarray[10]; 
    populate_array(myarray, 10, getNextRandomValue); 
    ... 
} 

Как вы уже видели выше, что еще я могу добиться реализации обратного вызова с помощью простой функции, так почему указатель использовать функции для выполнения обратного вызова. (то есть зачем передавать ссылку), когда я могу обойтись без этого.

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

+0

Они работают одинаково - они являются указателями на функции. Подобно тому, как (в контексте вашего 'main')' myarray' и '& myarray' оба указывают на одно и то же. –

+0

@DrewMcGowen Почти там. 'myarray' и' & myarray' не указывают на одно и то же. –

+0

Итак, почему люди предпочитают 'int (* foo) (void)' вместо 'int foo()' –

ответ

2
void populate_array(int *array, size_t arraySize, 
     int getNextValue(void)) // Note that, here I use normal function call. 

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

Рассмотрим эту аналогию: вы можете определить новый тип для указателей на int и использовать его в объявлении функции

typedef int* intptr_t; 
void myFunction(intptr_t ptr) { 
    ... 
} 

или вы можете сказать, что ptr является указателем на int внутри декларации:

void myFunction(int* ptr) { 
    ... 
} 

Таким же образом, вы можете определить тип вашего указателя функции, прежде чем использовать его в объявлении

typedef void generator_t(void); 
void populate_array(int *array, size_t arraySize, generator_t getNextValue) { 
} 

или вы могли бы сказать, что getNextValue - это указатель на функцию, использующий альтернативный синтаксис из вашего сообщения.

Одна из причин использования указателей функций - это проверка согласованности, когда вы хотите создавать массивы указателей функций: если в вашей библиотечной функции используется указатель функции, определенный внутри объявления этой функции, вам нужно будет повторно создать ту же декларацию в вашем собственном коде, чтобы создать массив указателей, которые вы собираетесь передать библиотеке в качестве указателей. Это может привести к несогласованности, которая будет видна только в точке вызова функции библиотеки, а не в точке объявления массива, что затрудняет отслеживание потенциальных проблем.

+0

Итак, зачем это делать, если мы можем сделать это выше –

+0

@ ashish2expert Должен ли я повториться? «Потому что он более явный, 2. ближе к истине». –

+0

@ ashish2expert Наличие указателя, определенного в описании внешней функции, облегчает передачу указателей, предназначенных для потребления внутри целевой библиотеки. – dasblinkenlight