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.