从 C 中的线程返回值
Returning a value from a thread in C
你好,我很难理解如何从 c 中的线程 returned 值。我有这个工作示例:
#define NTHREADS 4
void *neg (void * param) {
int *l;
l=(int *) param;
int *r=(int *)malloc(sizeof(int));
*r=-*l;
return ((void *) r);
}
int main (int argc, char *argv[]) {
pthread_t threads[NTHREADS];
int arg[NTHREADS];
int err;
for(long i=0;i<NTHREADS;i++) {
arg[i]=i;
err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i]));
if(err!=0)
error(err,"pthread_create");
}
for(int i=0;i<NTHREADS;i++) {
int *r;
err=pthread_join(threads[i],(void **)&r);
printf("Resultat[%d]=%d\n",i,*r);
free(r);
if(err!=0)
error(err,"pthread_join");
}
return(EXIT_SUCCESS);
}
我觉得很难理解的是:
函数 neg returns 一个在 (void *) 中转换的指针 * r 指向堆中的一个值。因此 return 基本上是堆的地址。然后在 pthread_join 中,我们通过执行 &r 获得 return 值(这本身似乎不合逻辑?抓住地址的地址?)然后转换为指针的指针?我们为什么要这样做?
感谢您的帮助!
考虑这段代码,它完全有效并打印出“5 5 5 5”。
int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
printf("%d %d %d %d\n", x, *p, **pp, ***ppp);
return 0;
C 允许您拥有任意深度的指针,并使用相应数量的寻址运算符进行初始化。在您的示例中,您分配了一个 int *
并且该函数必须 return 一个 void **
,因此您必须两次取消引用结果并将其转换,这是通过转换 int *
.
所以,"grab the adress of an adress?" 是的! 好吧,一个 pointer 的地址,它可能保存一个 int 的地址, 或另一个指针。
Then in pthread_join we get that return value by doing &r (which by
itself seems illogical? grab the adress of an adress?) then casting to
a pointer of a pointer? Why do we do that?
首先您需要了解的是 线程 函数不直接 return 值;他们使用 pthread_exit()
或 returning 值(如您的示例)将值发送到 pthreads 库,并且
它是通过调用 pthread_join()
检索的(通过使用线程标识符)。由于 return 值是一个指针,你必须
将指针传递给指针以从 pthread_join()
函数中检索它。
为了便于理解,请考虑以下伪代码:
/* thread */
void *neg(void *arg)
{
return ptr; // let's say "ptr" is stored in the library as "retval_thread_id"
}
int pthread_joing(pthread_t thread_id, void **retval)
{
*retval = retval_thread_id;
}
int main(void)
{
rc = pthread_join(threads[i],(void **)&r);
}
那么,如何在不使用指向指针的指针的情况下从 pthread_join()
检索指针 retval_thread_id
?
这与将 ptr-to-ptr 传递给函数并且函数存储在传递的指针的指针没有什么不同:
void func(int **p)
{
*p = malloc(10 * sizeof *p);
}
int main(void)
{
int *p;
func(&p);
}
顺便说一下,您所做的所有转换(除了调用 pthread_join()
中的转换——如果您将 r
声明为 void *r;
,您也不会这样做。 ) 是不必要的。 void 指针可以分配给 C 中的任何其他数据指针而无需强制转换。
你好,我很难理解如何从 c 中的线程 returned 值。我有这个工作示例:
#define NTHREADS 4
void *neg (void * param) {
int *l;
l=(int *) param;
int *r=(int *)malloc(sizeof(int));
*r=-*l;
return ((void *) r);
}
int main (int argc, char *argv[]) {
pthread_t threads[NTHREADS];
int arg[NTHREADS];
int err;
for(long i=0;i<NTHREADS;i++) {
arg[i]=i;
err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i]));
if(err!=0)
error(err,"pthread_create");
}
for(int i=0;i<NTHREADS;i++) {
int *r;
err=pthread_join(threads[i],(void **)&r);
printf("Resultat[%d]=%d\n",i,*r);
free(r);
if(err!=0)
error(err,"pthread_join");
}
return(EXIT_SUCCESS);
}
我觉得很难理解的是:
函数 neg returns 一个在 (void *) 中转换的指针 * r 指向堆中的一个值。因此 return 基本上是堆的地址。然后在 pthread_join 中,我们通过执行 &r 获得 return 值(这本身似乎不合逻辑?抓住地址的地址?)然后转换为指针的指针?我们为什么要这样做?
感谢您的帮助!
考虑这段代码,它完全有效并打印出“5 5 5 5”。
int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
printf("%d %d %d %d\n", x, *p, **pp, ***ppp);
return 0;
C 允许您拥有任意深度的指针,并使用相应数量的寻址运算符进行初始化。在您的示例中,您分配了一个 int *
并且该函数必须 return 一个 void **
,因此您必须两次取消引用结果并将其转换,这是通过转换 int *
.
所以,"grab the adress of an adress?" 是的! 好吧,一个 pointer 的地址,它可能保存一个 int 的地址, 或另一个指针。
Then in pthread_join we get that return value by doing &r (which by itself seems illogical? grab the adress of an adress?) then casting to a pointer of a pointer? Why do we do that?
首先您需要了解的是 线程 函数不直接 return 值;他们使用 pthread_exit()
或 returning 值(如您的示例)将值发送到 pthreads 库,并且
它是通过调用 pthread_join()
检索的(通过使用线程标识符)。由于 return 值是一个指针,你必须
将指针传递给指针以从 pthread_join()
函数中检索它。
为了便于理解,请考虑以下伪代码:
/* thread */
void *neg(void *arg)
{
return ptr; // let's say "ptr" is stored in the library as "retval_thread_id"
}
int pthread_joing(pthread_t thread_id, void **retval)
{
*retval = retval_thread_id;
}
int main(void)
{
rc = pthread_join(threads[i],(void **)&r);
}
那么,如何在不使用指向指针的指针的情况下从 pthread_join()
检索指针 retval_thread_id
?
这与将 ptr-to-ptr 传递给函数并且函数存储在传递的指针的指针没有什么不同:
void func(int **p)
{
*p = malloc(10 * sizeof *p);
}
int main(void)
{
int *p;
func(&p);
}
顺便说一下,您所做的所有转换(除了调用 pthread_join()
中的转换——如果您将 r
声明为 void *r;
,您也不会这样做。 ) 是不必要的。 void 指针可以分配给 C 中的任何其他数据指针而无需强制转换。