从 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 中的任何其他数据指针而无需强制转换。