从C

时间:2016-05-24 11:19:14

标签: c multithreading pthreads

您好我很难理解如何从c中的一个线程返回一个值。我有这个工作的例子:

#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返回一个指向(void *)的指针* r,指向堆中的值。因此基本上将地址返回到堆中。然后在pthread_join中我们通过做&amp; r得到那个返回值(这本身看起来不合逻辑?抓住地址的地址?)然后转换为指针的指针?为什么我们这样做?

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

考虑这段代码,该代码完全有效并打印&#34; 5 5 5 5&#34;。

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 *并且该函数必须返回void **,因此您必须取消引用结果两次并将其强制转换,这是通过转换int *完成的。

那么,&#34;抓住地址的地址?&#34; Yup!嗯,指针的地址,它可能包含int的地址或另一个指针。

答案 1 :(得分:0)

  

然后在pthread_join中我们通过做&amp; r得到那个返回值   本身似乎不合逻辑?抓住地址的地址?)然后施展到   指针的指针?为什么我们这样做?

首先需要了解的是线程函数不会直接返回值;他们使用pthread_exit()将值发送到pthreads库或返回一个值(如您的示例中所示)和 通过调用pthread_join()(通过使用线程标识符)检索它。由于返回值是指针,因此必须 传递一个指向指针的指针,以便从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);
}

那么,如何在不使用指针指针的情况下从retval_thread_id检索指针pthread_join()? 这与将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中的任何其他数据指针。