我很难理解为什么pthread_join
的retval
参数是void**
。我读过手册页,试着把它包起来,但我仍然无法完全理解。我无法说服自己retval
不可能是void*
。有人能启发我一下吗?
提前非常感谢!
这是因为您应该向pthread_join
提供void*
的地址。pthread_join
将把pthread_exit(void*)
提供的地址写入变量(您提供的地址)。
示例场景:
typedef struct {
// members
} input_data;
typedef struct {
// members
} output_data;
起始螺纹侧:
input_data id;
pthread_create(..., start_routine, &id);
void* start_routine(void *ptr) {
input_data *id = ptr;
output_data *od = malloc(sizeof *od);
// use the input data `id`, populate the output data `od`.
pthread_exit(od);
}
连接侧:
output_data *od;
pthread_join((void**) &od);
// use `od`
free(od);
足够简单。提供给pthread_create
的线程func的返回值为void*
;pthread_join
应该将这个值返回给调用者。
它不能将其作为函数返回类型返回(因为它已经返回int
来指示调用的总体状态)。唯一的其他方式是through-out参数。
C输出参数的方法是使用指向参数实际类型的指针,也就是说,如果你想将int
作为输出参数,那么参数的类型应该是int*
。如果out参数是void*
(因为这是从pthread func返回的!),那么参数的类型将变为void**
。
作为练习,您可以尝试自己编写类似的代码——首先,创建一个返回void*
(比如void* foo()
)的函数,然后尝试编写另一个调用foo()
并将结果反馈给调用者的函数。
退出的线程将提供一个指向某些数据的指针。pthread例程不知道数据的类型,所以它们接收作为void *
的指针。
CCD_ 22的呼叫者将接收该CCD_ 23。由于函数返回值用于其他用途,因此必须通过参数接收void *
。因此,调用者必须传递一个指向pthread_join
将把void *
放在哪里的指针。该指针是指向作为void **
的void *
的指针。
来自手册页:
如果retval不为NULL,则pthread_join()将目标线程的退出状态(即目标线程提供给pthread_exit(3)的值)复制到retval指向的位置。
让我们看看pthread_exit
的签名。
noreturn void pthread_exit(void *retval);
这意味着,如果我们想从线程返回int
,它看起来像这样:
void* foo() {
// ...
int value = 255;
pthread_exit(&value);
}
这样做是因为编译器不在乎它是int*
还是void*
,无论哪种方式,它都是相同大小的指针。
现在,我们想要使用pthread_join
实际提取线程的返回值。
void bar() {
pthread_t thread_id;
int *returnValue;
// create thread etc...
// the original type of returnValue was an `int*` so when we pass it in
// with "&" it's now become `int**`
pthread_join(thread_id, &returnValue);
printf("%dn", *returnValue); // should print 255
}
在普通英语中,pthread_join
获取一个指针,并将其地址设置为指向线程中的retval
。它是void**
,因为我们需要指针的地址才能将底层指针设置为我们想要的。