我试图打印线程的返回值,发现我仍然对双空指针的概念感到困惑。
我的理解是, void* 是指向任何数据类型的指针,可以通过适当的强制转换取消引用,但否则引用的“级别”会像常规类型指针一样被保留(即,您不能期望得到与您放入 **(int **)depth2
的值相同,只需取消引用一次即可,如 *depth2
。)。
但是,在我为线程返回打印而整理的代码(下面)中,似乎我没有取消引用一个空指针当我将其转换到 (int) 时。这是地址被用作值的情况吗?如果是这样,这是从线程返回的正常方式吗?不然我还缺什么??
(我知道在线程内操作数据的更安全方法可能是调用者级存储,但我对这种情况非常感兴趣,以及我不明白 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
相当于说
“你会在地址 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
关于c - 取消引用 void * 就像 (int) -- 标准做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60875880/