Предупреждение при использовании указателей на функции в C - PullRequest
2 голосов
/ 08 мая 2009

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

typedef void * Pointer;
void tree_destroyLineage(Tree greatest_parent, void *dataDestructor(Pointer data));

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

tree_destroyLineage(decision_tree, free);

И это заставляет меня получить сообщение "warning: passing argument 2 of 'tree_destroyLineage' from incompatible pointer type". Моим первым предположением было то, что компилятор не мог выяснить во время компиляции, что Pointer и void * - это одно и то же, поэтому я попытался создать обе функции с точно такими же типами указателя на функцию, которая «передает» вызов на free() и изменение объявления указателя функции для принятия void * вместо указателя. Оба подхода дали мне одно и то же предупреждение в одном и том же месте.

Что я делаю не так и как мне это решить?

Ответы [ 4 ]

10 голосов
/ 08 мая 2009

Я считаю, что правильная подпись для функции типа free:

void (*freefunc)(void*)

не

void *dataDestructor(Pointer data)
7 голосов
/ 08 мая 2009

Я не уверен насчет вашей библиотеки, но у моего free нет возвращаемого значения (т. Е. Оно пустое). Он не возвращает пустой указатель.

Если вы хотите, чтобы вторым аргументом был указатель на функцию, которая возвращает void и принимает в качестве аргумента указатель void, я считаю, что вам нужно:

void (* fn) (void *)

а не

void * fn (void *)

что у вас есть.

4 голосов
/ 08 мая 2009
void tree_destroyLineage(Tree greatest_parent, 
                          void *dataDestructor(Pointer data));

должно быть:

void tree_destroyLineage(Tree greatest_parent, 
                          void (*dataDestructor)(Pointer data));
2 голосов
/ 08 мая 2009

Попробуйте это:

void tree_destroyLineage(Tree greatest_parent, void (*dataDestructor)(void *data));

Использовать typedef для пустого указателя просто глупо.

Редактировать: проблема в том, что без скобок вокруг *dataDestructor компилятор считает, что функция возвращает void *, а не void. Скобки сообщают компилятору, что функция возвращает void, но является указателем на функцию.

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