将函数指针强制转换为C中的另一个函数指针是否安全?

F0urAt

将这2个函数强制转换为回调指针类型然后在不强制返回的情况下调用它们是否安全?

typedef void (*callback)(int i, ...);
    
void foo() {
    // something.
}

void foo2(int i, int j) {
    // something.
}
    
int main(void)
{
    callback c = (callback)&foo, c2 = (callback)&foo2;
    (*c)(0); (*c2)(0,1); 
    return 0;
}
约翰·布林格

将这2个函数强制转换为回调指针类型然后在不强制返回的情况下调用它们是否安全?

否。callback从语言规范的“兼容”的意义上讲,这两个函数的类型与type不兼容,因此,通过类型的指针调用这两个函数中的任何一个都会callback引起未定义的行为。总的来说,非可变函数类型永远不会与可变函数类型兼容,并且在实践中,许多实现对一种类型使用的调用约定与对另一种类型使用的调用约定不同,因此,甚至没有理由希望将一种函数调用为如果它是其他品种,则将以任何一致的方式产生所需的效果。

您有几种选择,其中包括:

  • 为不同的目的使用不同的回调类型,每种类型都适合其预期的回调接口。这样,您可以完全避免转换回调函数。这是我的建议。它实现了最佳的类型安全性,并且您需要以某种方式始终跟踪实际的回调类型是什么,以便可以正确调用它。

  • 使用函数指针类型的并集。回调说明符分配给联合的适当成员,而回调呼叫者选择适当的成员。

    typedef union {
        int (*unary)(int i);
        int (*binary)(int i, int j);
    } callback;
    
    // ...
    
    callback cb1 = { .unary = foo };
    callback cb2 = { .binary = foo2 };
    cb1.unary(1);
    cb2.binary(1, 2);
    

    您甚至可以使用带标签的联合,该联合还附带有关使用哪个成员的信息。使用起来会有些复杂,但是它将为您提供一种实现附加类型安全性的方法。如果您需要一种可以传递多种回调类型的数据类型,则我的后备建议就是这种方法的一种变体

  • 选择一种满足您所有需求的回调类型。一种实现方法是为它提供一个type参数void *,通过该参数回调函数可以接受任何数量和类型的输入,例如,指向合适结构类型的指针。

    typedef int (*callback)(void *);
    struct one_int { int i1; };
    struct two_int { int i1, i2; };
    int foo(void *args) {
        struct one_int *one_int = args; // ...
    }
    int foo2(void *args) {
        struct two_int *two_int = args; // ...
    }
    
  • 选择任何功能类型作为callback强制转换为该类型,然后返回到原始类型以进行呼叫。

  • 指定没有原型的回调类型。在C语言中,如果不属于该函数定义的函数声明未指定参数类型列表,则意味着没有提供有关参数的信息(与C ++不同,在C ++中,这意味着该函数没有参数) 。这与需要任何特定数量的参数(但不可​​变参数)的函数兼容,只要将默认参数提升应用于参数类型即可产生兼容的类型。int在这方面,类型是一种精细的参数类型。可能会出现问题的主要类型是小于int,plus的整数类型float

    typedef int (*callback)();
    

    这将完全允许您为示例中的特定功能类型描述用法。

    callback cb1 = foo;
    callback cb2 = foo2;
    
    (*cb1)(1);  // or just cb1(1)
    (*cb2)(2);  // or just cb2(1, 2)
    

    与另一个答案的主张相反,对该方法的支持并不构成对迄今为止已发布的C语言规范的任何版本的扩展。支持它是符合C89,C99,C11和C17中任何一个的要求。但是,它已在C17中声明为“过时”,这构成了警告,可能会将其从语言规范的某些将来版本中删除。我希望确实可以删除它,可能会在下一个规范版本中将其删除,尽管过时并不能保证一定会删除。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将指针强制转换为从C中的int函数返回的int是否安全?

将int指针转换为void指针并返回以在另一个函数中使用该值?

为什么在C ++中可以将一个类的指针强制转换为另一类的指针?

引用函数中另一个指针的C指针

将this指针传递给另一个函数的安全方法是什么?

C++ 函数绑定 - 强制将 `this` 强制转换为另一个类可能吗?

将缺失的参数添加到另一个函数中的函数指针

在 C 中的另一个函数中填充指向函数的指针数组

将子对象指针转换为基类(从另一个名称空间)指针

是否可以将C ++指针分配给Python对象的属性,然后在另一个C ++函数中将其作为C ++指针检索?

是否将LONG强制转换为函数指针?

将指针从一个函数传递到另一个函数

如果我只能访问指针变量,如何在调用函数时将指向 struct 的指针传递给 C 中的另一个函数

将指向一个C函数的指针作为另一个函数的参数传递

C ++将函数指针分配给另一个

传递c ++对象作为指针,以在Rcpp中的另一个函数中重用

修改函数内的指针(将另一个指针作为参数传递)

如何使用指针C ++将一个类的析构函数转换为另一个类?像单向列表容器类和节点类之类的东西

是否可以将struct指针转换为c中的函数指针?

如何将void指针强制转换为函数指针

在Golang错误中从一个指针转换为另一个指针类型

如何在C ++ 17中将强制转换函数指针静态转换为noexcept?

将指向lambda函数的指针分配给指向另一个lambda函数的指针

使用另一个类的函数指针

将指向结构的第一个成员的指针强制转换为指向该结构的指针是否合法?

将结构体指针转换为另一个结构体

添加到函数指针,以获得指向另一个函数的指针?

简单地将指针传递给另一个函数失败

如何将子矩阵作为指针传递给另一个函数