您能解释一下(void (*)(void *))
在以下表达式中的含义:
(void (*)(void *))pthread_mutex_unlock
答案 0 :(得分: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
等等有限制。 。)阅读代码时更容易发现。
答案 1 :(得分: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...
有更好的方法可以做到这一点,没有未定义的行为(由于bodgy强制转换)...例如使用std::mutex
和std::lock_guard
。
答案 2 :(得分:1)
这条线不是“自给自足”
“按原样”它告诉你指向函数pthread_mutex_unlock()的指针将被强制转换为:
指向函数的指针,该函数将指向任何东西的指针作为参数并且不返回任何内容。