【问题标题】:Passing a void pointer to a function pointer将 void 指针传递给函数指针
【发布时间】:2013-02-13 03:07:07
【问题描述】:

简而言之,我试图使用 void 指针作为函数指针的参数,但出现编译器错误“无效使用 void 表达式”。

我有一个双向链表(DLL),其节点结构如下:

typedef struct DL_LIST
{
    uint16 tag;                 /* Object ID tag */
    struct DL_LIST *previous;
    struct DL_LIST *next;
    void *object;               /* A pointer to this node's object */
    uint32 size;                /* The size of this node's object, in bytes */
} DL_LIST;

我还有以下用于删除单个此类节点的功能:

void dl_delete(DL_LIST *node, void (*dl_destructor)(void*)) {
    if (node != NULL) {
        dl_extract(node);       /* Removes the node from the list */

        if (node->object != NULL) {
            (*dl_destructor)(node->object);

            free(node->object);
        }

        free(node);
    }
}

节点提取函数在哪里:

DL_LIST *dl_extract(DL_LIST *node) {
    if (node != NULL) {
        if (node->previous != NULL) {
            node->previous->next = node->next;
        }

        if (node->next != NULL) {
            node->next->previous = node->previous;
        }

        node->previous = NULL;
        node->next = NULL;
    }

    return node;
}

这里的想法是能够为每个可能存储在节点中的object 类型传递一个单独的析构函数。此析构函数将指向对象的指针作为参数,用于释放 object 的子代正在使用的任何堆内存。

当我尝试从旨在删除整个 DLL 的函数中调用 dl_delete() 时,出现上述错误:

void dl_destroy(DL_LIST **list, void (*dl_destructor)(void*)) {
    DL_LIST *marker;
    DL_LIST *previous_node;

    if (*list != NULL) {
        previous_node = (*list)->previous;

        while (previous_node != NULL) {
            marker = previous_node->previous;
            dl_delete(previous_node, (*dl_destructor)(previous_node->object));
            previous_node = marker;
        }

        /* Code removed for brevity */
    }
}

我已阅读this 函数指针简介,但仍无法确定如何解决该问题。对我做错了什么的解释将不胜感激。

【问题讨论】:

  • 为了完整起见,您可能希望在问题中包含 dl_extract(node) 函数。
  • @Floris 谢谢你的建议。

标签: c function-pointers void-pointers


【解决方案1】:

这一行

dl_delete(previous_node, (*dl_destructor)(previous_node->object));

需要dl_delete(previous_node, dl_destructor);

也在dl_delete这行(*dl_destructor)(node->object);

应该是dl_destructor(node->object);

另外,为了安全起见,我喜欢在尝试使用它们进行调用之前检查我的函数指针是否不为空

所以在 dl_delete 中类似于:-

if(dl_destructor!=NULL) dl_destructor(node->object);

【讨论】:

  • 在您第一次推荐的更改 Keith 中,您为什么要从 dl_destructor 函数中删除对象参数?没有它,函数如何工作?
  • 因为您想将指针传递给函数.....您似乎想要做的是调用该函数。一旦你声明了一个函数指针。它充当普通指针。当你想调用它指向的函数时,你只需像调用函数一样调用指针
  • 很难解释,但唯一一次使用有趣的函数指针语法是在声明它的时候。 (很多时候人们 typedef 它)
猜你喜欢
  • 2013-06-25
  • 2018-08-25
  • 1970-01-01
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 2012-11-08
相关资源
最近更新 更多