6

我有一个看起来像这样的事件结构

typedef struct {
    void* fn;
    void* param;
} event;

如何通过指针调用此函数作为结构的一部分。例如,这些不起作用:

event->(*function)();
event->function();
(*event->function)();

我想知道如何在使用和不使用附加 void* 参数的情况下进行函数调用。我最初使用此链接作为参考:

http://www.cprogramming.com/tutorial/function-pointers.html

我以前使用过这些函数指针,但无法正确获取语法。

4

4 回答 4

7

您需要void*先将指针转换为函数指针:

#include <stdio.h>

typedef struct {
    void* fn;
    void* param;
} event;

void print()
{
        printf("Hello\n");
}


int main()
{
    event e;
        e.fn = print;
        ((void(*)())e.fn)();
        return 0;
}

当然,如果这真的是你想要的。如果您希望结构包含指向函数的指针,而不是void*指针,请在声明中使用正确的类型:

typedef struct {
    void (*fn)();
    void* param;
} event;

在这里,您已fn声明为指向void函数的指针,以及paramasvoid*指针。

于 2013-09-19T16:21:50.983 回答
1

event是一个类型,而不是一个对象或表达式。您不能访问结构类型的成员,只能访问结构类型的对象。

所以给出:

typedef struct {
    void* fn;
    void* param;
} event;

你需要有一个 type 的对象event,并且你需要给它的成员赋值。

在您的问题中,您将fn其用作成员名称,但随后您引用了名为function. 我在这里假设它们应该是相同的东西,并且fn应该指向某些功能。

您不能将函数指针可移植地存储在void*. 在许多(可能是大多数)实现中,您可以摆脱它,但语言不能保证。(有些系统函数指针大于数据指针,将函数指针转换为void*丢失信息。)另一方面,所有指向函数的类型都可以相互转换,并且保证往返转换给你原始的指针值。

我会假设(我在这里做了很多假设,因为您没有提供很多信息)您想要fn指向一个接受void*参数但不返回结果的函数;然后做param一个void*有意义的。为了与该假设保持一致,我们可以更改您的类型定义:

typedef struct {
    void (*fn)(void*);
    void *param;
} event;

void (*fn)(void*);语法并不完全明显。我曾经cdecl构造它。)

现在您可以定义一个类型的对象event

event e = { some_func, NULL };

您必须在some_func某处定义,如

void some_func(void *param { /* ... */ }

或同等学历。event现在您可以通过对象间接调用该函数e

e.fn(e.param);

或者,如果有一个指向 a 的指针更方便event

event *ptr = malloc(sizeof *ptr);
if (event == NULL) {
    /* error handling here */
}
ptr->fn = some_func;
ptr->param = NULL;

event并且您可以在指向的指针和它指向的对象中包含的函数指针上使用间接event

ptr->fn(ptr->param);

根据您要完成的任务,您可能希望fn能够指向不同类型的函数。如果这样做,则必须在通过它进行调用之前转换(使用显式转换)e.fnptr->fn它指向的函数的实际类型。不能盲目混用不同类型的函数指针;如果这样做,结果要么是编译时错误,要么是运行时未定义的行为。您可以将void (*)(void)(指向不带参数且不返回结果的函数的指针)用作“通用”函数指针类型,但与void*任何类型的转换不同,您需要的类型必须是显式的。)

我想知道如何在使用和不使用附加void*参数的情况下进行函数调用。

要调用不带参数的函数,只需()在函数调用中使用。但是同样,对于给定的函数,您不能选择使用或不使用参数来调用它;调用必须与定义匹配。(除了可能的可变参数函数printf,但您仍然需要一个正确类型的函数指针,并且不能在没有参数的情况下调用可变参数函数。)

于 2013-09-19T18:00:16.680 回答
1

如果我理解正确,您可能正在寻找这个:

typedef struct {
    void (*fn)();
    void (*param)();
} event;


event *E;

E->fn();
E->param();
于 2013-09-19T16:23:40.617 回答
0

在不会导致未定义行为 (UB) 的有效 C 程序中,您尝试执行的操作是不可能的。void *可以指向一个有效对象,在数组的最后一个对象之后一个字节或指向NULL,但函数不是对象。您可以做的是在不同的函数指针之间进行转换。但请记住,在调用函数指针之前,您必须将函数指针转换回正确的类型。调用指向具有不同类型的函数的函数指针会导致 UB。

许多嵌入式平台都有单独的函数存储,并且函数没有加载到 RAM 中,指向的指针void *通常小于指向函数的指针。在与 Posix 兼容的平台上,您可以在函数指针之间void *来回转换,而不会导致 UB。但这是一个 Posix 扩展,并且是函数所必需的dlsym(),它不是 C 的一部分。

于 2020-09-04T09:36:20.077 回答