简体   繁体   中英

Returning a value from a thread in C

Hello i am having a hard time understanding how a value is returned from a thread in c. I have this working example:

#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);
}

What i find hard to understand is the following:

the function neg returns a pointer * r casted in (void *) pointing to a value in the heap. Thus returning an adress to the heap basically. 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?

Thanks for the help!

Consider this code, which is perfectly valid and prints "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 allows you to have any depth of pointers, initialized with a corresponding number of address-of operators. In your example, you allocated an int * and the function must return a void ** , so you have to dereference the result twice and cast it, which you accomplished by casting the int * .

So,"grab the adress of an adress?" Yup! Well, the address of a pointer , which may hold the address of an int, or another pointer.

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?

First thing you need to understand is that the thread function(s) do not return the value directly; they send the value to the pthreads library using pthread_exit() or returning a value (as in your example) and it's retrieved with a call to pthread_join() (by using the thread identifier). Since the return value is a pointer, you have to pass a pointer to pointer to retrieve it from pthread_join() function.

For the understanding purposes, consider this pseudo code:

/* 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);
}

So, how can you retrieve the pointer retval_thread_id from pthread_join() without using a pointer to pointer? This is nothing different than passing a ptr-to-ptr to a function and the function stores at the pointee of the passed pointer:

void func(int **p) 
{
    *p = malloc(10 * sizeof *p);
}

int main(void)
{
    int *p;
    func(&p);
}

By the way , all the casts you do (except the one in the call to pthread_join() -- You wouldn't this either if you declared r as void *r; .) are unnecessary. A void pointer can be assigned to any other data pointer in C without a cast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM