【问题标题】:Is it possible to cast struct pointer to function pointer in c?是否可以将结构指针转换为c中的函数指针?
【发布时间】:2020-11-22 04:03:07
【问题描述】:

从这里:ISO C Void * and Function Pointers,我找到了将(void*) 转换为函数指针的解决方法:

int
main(int argc, char *argv[])
{
    ...
    void (*funcp)(void);        /* Pointer to function with no arguments */
    ...
    *(void **) (&funcp) = dlsym(libHandle, argv[2]);
}

换句话说 - 取消引用双指针(另一个间接级别)。

现在仍然假设最终函数是 void(*)() 类型,但我想让转换可用于其他函数“类型”,例如可以接受一些参数。

然后我找到了另一种解决方法,如何将函数指针包装在 struct Why can't I cast a function pointer to (void *)? 中:

typedef struct
{
   void (*ptr)(void);
} Func;

Func vf = { voidfunc };

所以我想合并这两个想法,并可以通过 struct 将任意函数类型作为函数指针传递:

#include <stdio.h>

struct s{
    int a, b;
    void (*func)();
};

typedef struct{
    int (*add)(int,int);
} Func;

int add(int a, int b) { return a+b; }

int main(){
    Func f = {add};
    struct s foo = {.func=(void*)(&f)};
    printf("%i\n",f.add(1,2));
    printf("%i\n",foo.func(1,2));
}

不幸的是,它给出了错误:

invalid use of void expression

所以问题是,如何在printf 语句中将类型(void*) 转换为(int*)(int,int)

【问题讨论】:

  • 即使你改变了编译指针,它也永远不会工作。
  • 关于“我找到了转换的解决方法”:也许您的意思是您找到了转换的解决方法。强制转换是执行转换的运算符,您不需要变通方法将void * 强制转换为函数指针,因为您只需编写强制转换:void (*funcp)(void) = (void (*)(void)) dlsym(libHandle, argv[2]);。 C 标准没有定义,但允许。如果您在支持dlsym 的环境中工作,据记录返回void * 是代码或数据的地址,那么该环境必然支持将void * 转换为...
  • … 一个函数指针。它隐含地是与该环境一起使用的编译器的一部分(尽管这应该在文档中明确说明;使其隐含是低于标准的工程)。此外,如果 C 实现确实支持将 void * 转换为函数指针,它将通过简单的强制转换来实现——不太可能有任何实现不支持它,而是通过重新解释指针的位来支持它。是做。这增加了表示和别名的其他问题。
  • 您可以将dlsym 的返回值转换为适当的函数指针类型。我不明白你想用这些结构做什么,但它看起来像一个XY problem
  • Re “那么问题来了,如何将(void*) 类型转换回(int*)(int,int)?在 printf 语句中?”:不要那样做。没有理由这样做。要打印任何指针,请使用%p,而不是%i,并将其转换为void *(如果还没有的话)。

标签: c pointers casting function-pointers void-pointers


【解决方案1】:

即使您将函数更改为返回int (int (*func)();) 并最终编译,您的代码也是错误的。

调用函数指针实际上是对这个指针的解引用。

当你用结构体的地址分配函数指针时,调用这个函数实际上会执行结构体内部的数据——而不是函数引用的结构体成员。当然不会成功。

https://godbolt.org/z/GE464T

以下示例是一个 UB,但适用于 x86 和 arm 机器,仅用于说明目的..

struct s{
    int a, b;
    int (**func)();
};

typedef struct{
    int (*add)(int,int);
} Func;

int add(int a, int b) { return a+b; }

int main(){
    Func f = {add};
    struct s foo = {.func=(void*)(&f)};
    printf("%i\n",f.add(1,2));
    printf("%i\n",(*foo.func)(1,2));
}

https://godbolt.org/z/rKvGEG

或者如果你想在结构中使用void (**)() 指针

typedef int func();

struct s{
    int a, b;
    void (**func)();
};

typedef struct{
    int (*add)(int,int);
} Func;

int add(int a, int b) { return a+b; }

int main(){
    Func f = {add};
    struct s foo = {.func=(void*)(&f)};
    printf("%i\n",f.add(1,2));
    printf("%i\n",((func *)(*foo.func))(1,2));
}

https://godbolt.org/z/M9qzdf

typedef int func();

struct s{
    int a, b;
    void (*func)();
};

typedef struct{
    int (*add)(int,int);
} Func;

int add(int a, int b) { return a+b; }

int main(){
    Func f = {add};
    struct s foo = {.func=(void*)(&f)};
    printf("%i\n",f.add(1,2));
    printf("%i\n",(*((func **)foo.func))(1,2));
}

或者没有类型定义

struct s{
    int a, b;
    void (*func)();
};

typedef struct{
    int (*add)(int,int);
} Func;

int add(int a, int b) { return a+b; }

int main(){
    Func f = {add};
    struct s foo = {.func=(void*)(&f)};
    printf("%i\n",f.add(1,2));
    printf("%i\n",(*((int (**)())foo.func))(1,2));
}

https://godbolt.org/z/YG9xd7

【讨论】:

    猜你喜欢
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    相关资源
    最近更新 更多