简体   繁体   English

void* 指针指向的调用函数

[英]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函数的指针,将paramvoid*指针。

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.fnptr->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.

相关问题 当它被指针指向时调用 function 和不被指针指向时的区别 - difference between calling a function when it is pointed by a pointer and not pointed by a pointer 传递带有变量参数的函数作为void指针,并调用它 - passing function with variable parameter as void pointer, and calling it 如何访问由 void 指针指向的链表 - How to access a linked list pointed to by a void pointer void 表达式的无效使用; 从 void 指针指向的数组复制信息; 进入字符指针指向的数组 - Invalid use of void expression; copying info from array pointed to by void pointer; into array pointed to by char-pointer 使用void(*)(void)指针调用void函数(int),并使用参数准备堆栈 - Calling a void function(int) with a void(*)(void) pointer and prepare stack yourself with arguments 调用void函数将两个数字相加,然后处理总和的指针 - Calling a void function to add two numbers then dealing with the pointer of the sum 如何将指针返回到void *指向的数组中的数组位置? - How to return pointer to an array position in array pointed to by void*? 将指针存储在void *中的函数指针 - Storing the pointer to a function pointer in a void* 指向 void function 的指针 - Pointer to a void function 无效 function 带指针 - Void function with a pointer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM