【问题标题】:Function Pointers Casting in CC中的函数指针转换
【发布时间】:2021-03-23 08:31:06
【问题描述】:

为什么我需要删除函数指针转换才能使用如下所示的函数?

编译:

#include <stdio.h>

int print_int(int i){
    printf("%d", i);
    return i;
}
typedef int (*print_int_func) (int);

int main(){
    void** p = malloc(1*sizeof(print_int_func*));
    p[0] = (print_int_func*)print_int;

    ((print_int_func)p[0])(2); // This Compiles
    ((print_int_func*)p[0])(2); // This does NOT
    
    return 0;
}

【问题讨论】:

  • 如果你分配给void**,你需要使用malloc(1 * sizeof(void*))sizeof 的参数始终是目标类型,* 少一个。
  • @Barmar 我正在尝试将函数存储在 void 指针数组中。目前它有效。但是我试图理解为什么指针声明是这样的。
  • 参见stackoverflow.com/questions/3941793/… 不能保证void* 可以保存函数指针。
  • 一般来说你不会取消引用函数指针。
  • @Barmar:他们不应该首先使用void *;函数指针不同于对象指针,void * 不是函数指针的泛型。此外,对于sizeof,最好使用分配的实际标识符和*,而不是重复类型:AnyType *p = malloc(NumberOf * sizeof *p);

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


【解决方案1】:

声明typedef int (*print_int_func) (int);print_int_func 声明为指向特定类型函数的指针。所以(print_int_func)p[0]p[0] 转换为指向函数的指针,但(print_int_func*)p[0]p[0] 转换为指向函数指针的指针。因此,结果是指向对象的指针(该对象是指向函数的指针)。由于它是一个对象,而不是一个函数(或指向函数的指针),所以它不能像函数一样被调用。

此外,避免将void * 用于指向函数的指针。 void * 是指向对象的指针,C 标准没有定义指向对象的指针和指向函数的指针之间的转换。要创建指向函数的“通用”指针,只需选择任何函数类型并使用指向该类型的指针:

  • 存储指针时转换为选择的类型。
  • 调用函数类型时转换为实际函数类型。

例如,您可以声明任意类型:

typedef void (*CommonFunctionPointer)(void);

并将它们组成一个数组:

CommonFunctionPointer *p = malloc(N * sizeof *p);,

然后你可以在数组中存储任何函数指针:

p[i] = (CommonFunctionPointer) print_int;

并通过将数组中的指针转换回正确的类型来使用它:

((int (*)(int)) p[i])(2);.

【讨论】:

  • 谢谢!所以(print_int_func)p[0] 将 p[0] 转换为一个函数,以便可以调用它。
  • 关于对象与函数指针,它背后的基本原理是什么?是因为 C 在使用过程中没有对其完整性提供任何可靠的保证吗?
  • @IwataKurosawa:具体来说,它将p[0] 转换为指向函数的指针。函数调用运算符(表达式后的括号)仅调用指向函数的指针。当您使用函数名称(如sin(x))编写函数调用时,该函数会自动转换为指针。
  • (即使函数是通过取消引用指针创建的也是如此。如果你有一个指向函数的q并写(*q)(x)*q是一个函数,但它自动转换为指向函数的指针。然后您可以再次应用*(**q)(x) 调用相同的函数。(******q)(x) 也是如此。)
  • @IwataKurosawa:对象指针和函数指针是不同的,因为在某些计算机中,它们的地址管理方式不同,而 C 标准希望允许 C 在各种计算机上使用。
猜你喜欢
  • 2023-03-29
  • 2011-07-31
  • 2012-11-21
  • 1970-01-01
  • 2013-11-03
  • 2015-11-03
  • 2012-12-17
  • 2016-06-03
相关资源
最近更新 更多