像 (int) 一样取消引用 void *——标准做法?

Dereferencing void * just as (int) -- standard practice?

我试图打印线程的 return 值,发现我仍然对双空指针的概念感到困惑。

我的理解是 void* 是指向任何数据类型的指针,可以通过适当的转换取消引用,但除此之外,引用的 "levels" 会像常规类型指针一样被保留(即你不能期望通过仅像 *depth2. 那样取消引用一次来获得您放入 **(int **)depth2 中的相同值。)。

在我为我的线程-return-打印拼凑的代码(下面)中,似乎我没有取消引用一个void pointer 当我只是将它转换为 (int) 时。这是地址用作值的情况吗?如果是这样,这是从线程 returning 的正常方式吗?否则,我错过了什么?

(我知道在线程内操作数据的更安全的方法可能是调用者级存储,但我对这种情况很感兴趣,我不明白 void 指针是什么。 )

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *myThread(void *arg)
{
    return (void *)42;
}

int main()
{
    pthread_t tid;
    void *res;                                        // res is itself a void *

    pthread_create(&tid, NULL, myThread, NULL);
    pthread_join(tid, &res);                          // i pass its address, so void** now
    printf(" %d \n", (int)res);                       // how come am i able to just use it as plain int?

    return 0;
}

首先,pthread_join()的目的是更新void * 通过它的第二个参数给出,以获得的结果 线程函数(一个void *).
当您需要更新 int 时,如 scanf("%d", &my_var); 中的参数 是要更新的int的地址:一个int *.
同理,您可以通过提供 void **.

来更新 void *

在你例子的具体情况下,我们不使用返回的 void * 以正常方式:这是一个技巧!
由于指针可以被认为是一个计算字节的大整数 很长的一行,诀窍是假设这个指针可以简单地存储 一个不引用任何内存位置的整数值。

在你的例子中,返回 (void *)42,相当于说 "you will find something interesting at address 42".
但是这个地址从来没有放过任何东西!
这是个问题吗?不,只要没有人试图取消引用它 指针,以便在地址 42 处检索内容。

一旦pthread_join()被执行,变量res就有了 已更新并包含返回的 void *:在本例中为 42。
我们通过假设记忆的信息来执行反向技巧 在这个指针中不是指内存位置,而是一个简单的整数。

可以用,但是太丑了!
主要优点是您避免了 malloc()/free()

的昂贵成本
void *myThread(void *arg)
{
  int *result=malloc(sizeof(int));
  *result=42;
  return result;
}

...
int *res;
pthread_join(tid, &res);
int result=*res; // obtain 42
free(res);

避免此成本的更好解决方案是使用参数 线程函数。

void *myThread(void *arg)
{
  int *result=arg;
  *result=42;
  return NULL;
}

...
int expected_result;
pthread_create(&tid, NULL, myThread, &expected_result);
pthread_join(tid, NULL);
// here expected_result has the value 42