你能解释一下以下表达式中
(void (*)(void *))
的含义吗?(void (*)(void *))pthread_mutex_unlock
(void (*)(void *))
的含义吗?(void (*)(void *))pthread_mutex_unlock
外面的括号表示一个强制类型转换。括号里面的内容是要转换成的类型。
在这种情况下,它是一个指向函数(*)
的指针,接受一个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
的参数类型执行转换并丢弃返回类型。这样做可以避免调用者和被调用者对于参数和返回值空间需求的理解不同而导致堆栈损坏的潜在风险(尽管在实践中,对于被忽略的返回值,这可能很少是一个问题,但安全起见最好还是这样做)。(pthread_mutex_t*)mutex
转换替换为 static_cast<pthread_mutex_t*>(mutex)
,它执行等效转换,但读起来更容易且易于理解。如果您真的在使用C ++,则应该在每个地方都使用这些“C ++ 风格”的转换,因为它们有明确定义的语义(即您可以进行哪些限制的static_cast
、哪些限制的dynamic_cast
等),并且在阅读代码时更容易发现。这是将类型指向函数的指针进行 "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::mutex
和std::lock_guard
。