(void (*)(void *)) 的含义是什么?

6
你能解释一下以下表达式中 (void (*)(void *)) 的含义吗?
(void (*)(void *))pthread_mutex_unlock

1
我尝试了这个网站,但输出不是很清晰:将pthread_mutex_unlock转换为返回void的函数指针(指向void的指针)。 - Konstantin
2
@Konstantin:在cdecl语言中,函数的类型被表示为“function(<函数参数>)返回<返回类型>”。 - user1084944
@Hurkyl,感谢您的解释! - Konstantin
1
点赞以平衡。我认为提出这样的问题没有任何缺陷,C++语法很痛苦。 - Binkan Salaryman
@Binkan:点赞因为你认为一个问题有用是一回事。但如果你这样做是因为你想否定别人发表意见的机会,那就完全不同了。 - user1084944
3个回答

4

外面的括号表示一个强制类型转换。括号里面的内容是要转换成的类型。

在这种情况下,它是一个指向函数(*)的指针,接受一个void*参数,并返回void(即什么也不返回)。

它在这里用于将pthread_mutex_unlock进行类型转换,该函数具有以下签名:

int pthread_mutex_unlock(pthread_mutex_t*);

这样就可以将其用作某些期望函数类型的内容(例如回调函数)。

void function(void*);

请注意,这样做的智慧取决于所针对的平台。更安全(即更可移植)的方法是用正确签名的另一个函数包装该函数。
void pthread_mutex_unlock_wrapper(void *mutex)
{
    pthread_mutex_unlock((pthread_mutex_t*)mutex);
}

这将对pthread_mutex_unlock的参数类型执行转换并丢弃返回类型。这样做可以避免调用者和被调用者对于参数和返回值空间需求的理解不同而导致堆栈损坏的潜在风险(尽管在实践中,对于被忽略的返回值,这可能很少是一个问题,但安全起见最好还是这样做)。
注:最后要注意,由于您将问题标记为C++,您可以在包装函数中将(pthread_mutex_t*)mutex 转换替换为 static_cast<pthread_mutex_t*>(mutex),它执行等效转换,但读起来更容易且易于理解。如果您真的在使用C ++,则应该在每个地方都使用这些“C ++ 风格”的转换,因为它们有明确定义的语义(即您可以进行哪些限制的static_cast、哪些限制的dynamic_cast等),并且在阅读代码时更容易发现。

2

这是将类型指向函数的指针进行 "C风格" 强制转换,接受一个 void* 类型参数并不返回任何东西(由于返回类型不匹配而导致的 "未定义行为")。

请注意,pthread_mutex_unlock 本身的类型是:

int pthread_mutex_unlock(pthread_mutex_t *mutex); 

这可能是为了让一些知道如何调用期望void*函数的代码实际上回调pthread_mutex_unlock而使用的,这在大多数编译器上都可以工作,因为int返回值通常只是在调用者的寄存器中保留,所以忽略它不会影响堆栈布局或展开,但有些编译器可能会崩溃。


示例:

template <typename T>
class On_Destruction
{
  public:
    On_Destruction(void(*f)(T), T t)
      : f_(f), t_(t)
    { }

    ~On_Destruction() { f_(t_); }
  private:
    void (*f_)(void*);
    T t_;
};

...in some function...

    pthread_mutex_lock(my_mutex);
    On_Destruction<void*> guard((void(*)(void*))pthread_mutex_unlock,
                                (void*)&my_mutex);
    ...unlock when unwinding stack by return/break/throw etc...

有更好的方法可以做到这一点,而不会出现未定义的行为(由于不良转换)......例如使用std::mutexstd::lock_guard


1
这行文字并不是“自给自足的”。 “原样”的话,它告诉您pthread_mutex_unlock()函数的指针将被转换为: 接受任何指针作为参数且返回空值的函数指针。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接