像 (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
我试图打印线程的 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