用C++编写的函数指针

sud*_*03r 38 c++ casting function-pointers

我有一个由dlsym()返回的void指针,我想调用void指针指向的函数.所以我通过强制转换进行类型转换:

void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = static_cast<fptr>(gptr) ;
Run Code Online (Sandbox Code Playgroud)

我也试过reinterpret_cast但没有运气,虽然C演员似乎工作..

Fai*_*ali 50

在C++ 98/03中不允许直接将a转换void*为函数指针(不应使用任何强制转换编译).在C++ 0x中有条件地支持它(一个实现可以选择定义行为,如果它确定了它,那么它必须按照标准所说的那样做.A ,如C++ 98/03标准所定义的,意味着指向对象,而不是包含函数指针或成员指针. void*

知道你正在做的事情是依赖于实现的,这里有一个选项应该在大多数平台上编译和工作(假设32位指针,使用long long for 64 bit),即使它根据标准明显是未定义的行为:

void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<long>(gptr)) ;
Run Code Online (Sandbox Code Playgroud)

这是另一个应该编译和工作的选项,但与上面的内容相同:

fptr my_ptr = 0;
reinterpret_cast<void*&>(my_ptr) = gptr; 
Run Code Online (Sandbox Code Playgroud)

或者,在慢动作......

// get the address which is an object pointer
void (**object_ptr)() = &my_ptr;  

// convert it to void** which is also an object pointer
void ** ppv = reinterpret_cast<void**>(object_ptr);

// assign the address in the memory cell named by 'gptr' 
// to the memory cell that is named by 'my_ptr' which is
// the same memory cell that is pointed to 
// by the memory cell that is named by 'ppv'
*ppv = gptr;  
Run Code Online (Sandbox Code Playgroud)

它本质上利用了这样一个事实,即函数指针的地址是一个对象指针long long- 所以我们可以void (**object_ptr)()用来将它转换为任何其他对象指针:例如reinterpret_cast.然后我们可以跟回地址(通过解引用void**)到实际的函数指针并在那里存储gptr的值.

yuk - 绝不是明确定义的代码 - 但它应该按照你的期望在大多数实现上做.

  • 作为旁注,在中间演员表中使用的类型的更好选择可能是`size_t` - 它通常足够大以适合任何平台上的指针,即使这也不能保证.更好的是,在它可用的地方使用`<stdint.h>`/`<cstdint>`header和`intptr_t` typedef(C99,C++ TR1,C++ 0x). (8认同)
  • 事实上,"条件支持"的措辞是用dlsym()行为发明的 - 在2001年左右,人们注意到POSIXy系统的真正的C++编译器都接受了这种演员. (3认同)
  • @MSalters - 感谢背景:) - 这是可能已经开始这一切的 DR 的链接:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195 (2认同)