我有一个看起来像这样的事件结构
typedef struct {
void* fn;
void* param;
} event;
如何通过指针调用此函数作为结构的一部分。例如,这些不起作用:
event->(*function)();
event->function();
(*event->function)();
我想知道如何使用和不使用附加的void * param进行函数调用。我最初使用此链接作为参考:
http://www.cprogramming.com/tutorial/function-pointers.html
之前我使用过这些函数指针,但是在修复语法方面遇到了麻烦。
答案 0 :(得分:6)
首先需要将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
函数的指针,param
指向void*
指针。
答案 1 :(得分:1)
如果我理解正确,你可能正在寻找这个:
typedef struct {
void (*fn)();
void (*param)();
} event;
event *E;
E->fn();
E->param();
答案 2 :(得分:0)
event
是类型,而不是对象或表达式。您不能访问结构类型的成员,只能访问结构类型的对象。
所以给出:
typedef struct {
void* fn;
void* param;
} event;
您需要拥有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);
或者,如果将指针更加方便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.fn
或ptr->fn
到它通过它进行调用之前指向的函数的实际类型。你不能盲目地混合不同类型的函数指针;如果这样做,结果是编译时错误或运行时未定义的行为。您可以使用void (*)(void)
(没有参数的函数指针并且不返回任何结果)作为“通用”函数指针类型,但与void*
不同,您需要的所有类型的转换必须是显式的。)< / p>
我想知道如何使用和不使用额外的
void*
参数进行函数调用。
要调用不带参数的函数,只需在函数调用中使用()
即可。但同样,对于给定的函数,您无法选择是否使用参数调用它;调用必须与定义匹配。 (除了printf
之类的可变函数之外,你仍然需要一个正确类型的函数指针,并且不能在没有参数的情况下调用可变参数函数。)
答案 3 :(得分:0)
在没有引起未定义行为(UB)的有效C程序中,您要尝试执行的操作是不可能的。 void *
可以指向有效对象,该对象可以是数组的最后一个对象之后的一个字节,也可以指向NULL
,但是函数不是对象。
您可以做的是在不同的函数指针之间进行转换。
但是请记住,在调用函数指针之前,必须将函数指针转换回正确的类型。调用指向具有不同类型的函数的函数指针会导致UB。
许多嵌入式平台都有单独的函数存储,并且函数未加载到RAM中,指向void *
的指针通常小于指向函数的指针。
在与Posix兼容的平台上,您可以将指针转换成void *
的函数,然后再返回,而不会导致UB。但这是Posix扩展,并且是dlsym()
之类的函数所必需的,它不是C的一部分。