为什么在 pthread_join 中 retval 是一个 void**?

Why is retval a void** in pthread_join?

我很难理解为什么 pthread_joinretval 论点是 void**。我已经阅读了联机帮助页并试图全神贯注,但我仍然无法完全理解它。我无法说服自己 retval 不可能是 void*。有没有人能赐教一下?

非常感谢您!

这是因为你应该提供 void*pthread_join 的地址。 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的thread func的return值为void*pthread_join 应该 return 这个值给调用者。

它不能 return this 作为函数 return 类型(因为它已经 returning int 来指示调用的整体状态)。通过参数的唯一其他方法。

C 输出参数的方式是使用指向参数实际类型的指针——也就是说,如果您想将 int 作为输出参数,则参数类型为 int*。如果你的 out 参数是 void*(因为这是你从 pthread func 得到的 return!),参数的类型变成 void**.

作为练习,您可以尝试自己编写类似的代码 - 首先,创建一个 returns void*(比如 void* foo())的函数,然后尝试编写另一个调用 foo() 并将结果返回给调用者的函数。

退出线程将提供指向某些数据的指针。 pthread 例程不知道数据的类型,因此它们接收指针作为 void *.

pthread_join 的调用者将收到 void *。由于函数 return 值用于其他用途,因此必须通过参数接收 void *。所以调用者必须传递一个指向 pthread_join 将放置 void * 的指针。该指针是指向 void * 的指针,它是 void **.

来自联机帮助页:

If retval is not NULL, then pthread_join() copies the exit status of the target thread (i.e., the value that the target thread supplied to pthread_exit(3)) into the location pointed to by retval.

我们来看看pthread_exit的签名。

noreturn void pthread_exit(void *retval);

所以这意味着如果我们想从我们的线程中 return 一个 int 它看起来像这样:

void* foo() {
    // ...
    int value = 255;
    pthread_exit(&value);
}

这是可行的,因为编译器不关心它是 int* 还是 void*,无论哪种方式它都是相同大小的指针。

现在我们要使用 pthread_join.

实际提取线程的 return 值
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("%d\n", *returnValue); // should print 255
}

简而言之,pthread_join 获取一个指针并将其地址设置为指向您线程中的 retval。这是一个 void** 因为我们需要指针的地址才能将底层指针设置为我们想要的。