如何将void(*)()类型的指针转​​换为void *

时间:2017-07-16 23:30:36

标签: c++

如何将void(*)()类型的指针转​​换为void *

是否可以使用以下任何一个运算符?

  • const_cast
  • static_cast
  • dynamic_cast
  • reinterpret_cast

示例:编译以下所有内容(在Visual Studio 2017中尝试),我想知道它们在转换后是否都具有相同的结果。

void operation(void(*callback)()) {

    void* test1 = callback;
    void* test2 = static_cast<void*>(callback);
    void* test3 = reinterpret_cast<void*>(callback);
}

2 个答案:

答案 0 :(得分:4)

在ISO标准C ++中,没有从任何函数指针类型到任何对象指针类型的隐式转换。所以这条线是不正确的。

void* test1 = callback;

编译器在没有诊断的情况下接受此操作是一个错误 1 (你确实启用了警告,对吗?)

标准C ++中禁止在任何对象指针类型和函数指针类型(任一方向)之间使用

static_cast。控制规则见5.2.9:

  

否则,static_cast将执行下面列出的转换之一。不能使用static_cast明确执行其他转换。

由于上面或下面的规则都没有讨论函数指针强制转换,因此禁止行

void* test2 = static_cast<void*>(callback);

但是,这不一定是单独的编译器错误,因为其中一个规则允许static_cast用于完成任何隐式转换。

最后一行是唯一正确的:

void* test3 = reinterpret_cast<void*>(callback);

控制规则在reinterpret_cast(5.2.10)

的规范中提供
  

有条件地支持将函数指针转换为对象指针类型,反之亦然。这种转换的含义是实现定义的,除非实现支持两个方向的转换,将一种类型的prvalue转换为另一种类型并返回,可能具有不同的cv-qualification,将产生原始指针值。 / p>

1 使用/Za启用标准兼容模式时,Microsoft C ++编译器会正确拒绝复制初始化和static_cast次尝试:

  

source_file.cpp(8):错误C2440:'初始化':无法从void (*)(void)转换为void *

     

source_file.cpp(8):注意:指向的类型是不相关的;转换需要reinterpret_cast,C风格的转换   或函数式演员

     

source_file.cpp(9):错误C2440:static_cast:   无法从void (*)(void)转换为void *

     

source_file.cpp(9):   注意:指向的类型是不相关的;转换需要   reinterpret_cast,C风格的演员表或函数式演员

答案 1 :(得分:3)

在标准C ++中,从C ++ 11开始,它是有条件支持的,这意味着实现可能支持也可能不支持它,并且必须记录它是否受支持。

对于支持此强制转换的实现,要使用的适当强制转换运算符为reinterpret_cast。详细信息可以在C ++ 14标准[expr.reinterpret.cast] / 8中找到。

尝试将函数指针转换为没有强制转换([conv.ptr])或static_cast([expr.static.cast] / 5)的对象指针是错误的。如果您的编译器在标准模式下允许这样做并且没有发出诊断,则编译器不符合要求。

相关问题