[英]Calling function pointed by void* pointer
I have an event struct that looks like this我有一个看起来像这样的事件结构
typedef struct {
void* fn;
void* param;
} event;
How can I call this function by pointer as part of the struct.如何通过指针作为结构的一部分调用此函数。 For example, these do not work:
例如,这些不起作用:
event->(*function)();
event->function();
(*event->function)();
I want to know how to make the function call both with and without using the additional void* param.我想知道如何在使用和不使用额外的 void* 参数的情况下进行函数调用。 I was originally using this link as a reference:
我最初使用此链接作为参考:
http://www.cprogramming.com/tutorial/function-pointers.html http://www.cprogramming.com/tutorial/function-pointers.html
I've used these function pointers before, but have trouble getting the syntax correct.我以前使用过这些函数指针,但无法正确获取语法。
You need to cast void*
pointer to the function pointer first:您需要先将
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;
}
Of course, if this is really what you want.当然,如果这真的是你想要的。 If you want your struct to contain pointer to the function, instead of
void*
pointer, use the proper type at the declaration:如果您希望结构包含指向函数的指针,而不是
void*
指针,请在声明中使用正确的类型:
typedef struct {
void (*fn)();
void* param;
} event;
Here you have fn
declared as a pointer to the void
function, and the param
as void*
pointer.在这里,您将
fn
声明为指向void
函数的指针,将param
为void*
指针。
If I understood correctly, you're probably looking for this:如果我理解正确,您可能正在寻找这个:
typedef struct {
void (*fn)();
void (*param)();
} event;
event *E;
E->fn();
E->param();
event
is a type , not an object or expression. event
是一个类型,而不是一个对象或表达式。 You can't access a member of a structure type, only of an object of a structure type.您不能访问结构类型的成员,只能访问结构类型的对象。
So given:所以给出:
typedef struct {
void* fn;
void* param;
} event;
you need to have an object of type event
, and you need to assign values to its members.您需要有一个
event
类型的对象,并且需要为其成员分配值。
In your question, you use fn
as a member name, but then you refer to something called function
.在您的问题中,您使用
fn
作为成员名称,但随后您指的是名为function
东西。 I'll assume here that they're supposed to be the same thing, and that fn
is supposed to point to some function.我在这里假设它们应该是同一件事,并且
fn
应该指向某个函数。
You can't portably store a function pointer in a void*
.您不能将函数指针可移植地存储在
void*
。 On many, probably most, implementations you can get away with it, but it's not guaranteed by the language.在许多(可能是大多数)实现中,您可以避免使用它,但语言并不能保证它。 (There are systems were function pointers are bigger than data pointers, and converting a function pointer to
void*
loses information.) On the other hand, all pointer-to-function types are convertible to each other, and a round-trip conversion is guaranteed to give you the original pointer value. (有些系统的函数指针比数据指针大,将函数指针转换为
void*
会丢失信息。)另一方面,所有指向函数的类型都可以相互转换,往返转换是保证给你原始的指针值。
I'll assume (I'm making a lot of assumptions here because you didn't provide a lot of information) that you want fn
to point to a function that takes a void*
argument and doesn't return a result;我会假设(我在这里做了很多假设,因为你没有提供很多信息)你希望
fn
指向一个接受void*
参数并且不返回结果的函数; then making param
a void*
makes sense.然后使
param
成为void*
是有道理的。 For consistency with that assumption, we can alter your type definition:为了与该假设保持一致,我们可以更改您的类型定义:
typedef struct {
void (*fn)(void*);
void *param;
} event;
(The void (*fn)(void*);
syntax is not entirely obvious. I used cdecl
to construct it.) (
void (*fn)(void*);
语法不是很明显。我使用cdecl
来构造它。)
Now you can define an object of type event
:现在你可以定义一个
event
类型的对象:
event e = { some_func, NULL };
You have to have defined some_func
somewhere, as你必须在某处定义
some_func
,如
void some_func(void *param { /* ... */ }
or equivalent.或同等学历。 Now you can call that function indirectly through the
event
object e
:现在您可以通过
event
对象e
间接调用该函数:
e.fn(e.param);
Or, if it's more convenient to have a pointer to an event
:或者,如果有一个指向
event
的指针更方便:
event *ptr = malloc(sizeof *ptr);
if (event == NULL) {
/* error handling here */
}
ptr->fn = some_func;
ptr->param = NULL;
and you can use indirection both on the pointer-to- event
and on the function pointer contained in the event
object it points to:并且您可以在指向
event
的指针和它指向的event
对象中包含的函数指针上使用间接:
ptr->fn(ptr->param);
Depending on what you're trying to accomplish, you might want fn
to be able to point to functions of different types.根据您要完成的任务,您可能希望
fn
能够指向不同类型的函数。 If you do that, you must convert (with an explicit cast) e.fn
or ptr->fn
to the actual type of the function it points to before making a call through it.如果这样做,则必须在通过它进行调用之前将
e.fn
或ptr->fn
转换(使用显式转换) e.fn
ptr->fn
的函数的实际类型。 You can't blindly mix function pointers of different types;不能盲目混用不同类型的函数指针; if you do, the result is either a compile-time error or run-time undefined behavior.
如果这样做,结果要么是编译时错误,要么是运行时未定义的行为。 You can use
void (*)(void)
(pointer to function with no parameters and returning no result) as a "generic" function pointer type, but unlike with void*
any conversions to the type you need must be explicit.)您可以使用
void (*)(void)
(指向不带参数且不返回结果的函数的指针)作为“通用”函数指针类型,但与void*
不同的是,任何到您需要的类型的转换都必须是显式的。)
I want to know how to make the function call both with and without using the additional
void*
param.我想知道如何在使用和不使用额外的
void*
参数的情况下进行函数调用。
To call a function with no argument, simply use ()
in the function call.要调用不带参数的函数,只需在函数调用中使用
()
。 But again, for a given function, you can't choose to call it with or without a parameter;但同样,对于给定的函数,您不能选择带参数或不带参数来调用它; the call has to match the definition.
调用必须与定义相匹配。 (Except perhaps for variadic functions like
printf
, but you still need a function pointer of the correct type, and a variadic function can't be called with no arguments.) (除了像
printf
这样的可变参数函数,但您仍然需要一个正确类型的函数指针,并且不能在没有参数的情况下调用可变参数函数。)
What you are trying to do is not possible in a valid C program that does not cause undefined behavior (UB).在不会导致未定义行为 (UB) 的有效 C 程序中,您尝试执行的操作是不可能的。
void *
can point to a valid objects, one byte after the last object of an array or to NULL
, but functions are not objects. void *
可以指向一个有效的对象,在数组的最后一个对象之后一个字节或指向NULL
,但函数不是对象。 What you can do is converting between different pointer to function.您可以做的是在不同的指针之间进行转换。 But please keep in mind that you have to cast the function pointer back to the right type before you call the function pointer.
但请记住,在调用函数指针之前,您必须将函数指针转换回正确的类型。 Calling a function pointer that points to a function with a different type causes UB.
调用指向不同类型函数的函数指针会导致 UB。
Many embedded platforms have separate storage for functions and the functions are not loaded into RAM, there a pointer to void *
is often smaller than a pointer to function.许多嵌入式平台都有单独的函数存储,并且函数没有加载到 RAM 中,指向
void *
的指针通常小于指向函数的指针。 On Posix compatible platforms you can convert pointers to function to void *
and back, without causing UB.在 Posix 兼容平台上,您可以将函数指针转换为
void *
并返回,而不会导致 UB。 But that is a Posix extension and required for functions like dlsym()
, it is not part of C.但这是一个 Posix 扩展并且是
dlsym()
等函数所必需的,它不是 C 的一部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.