Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

casting long to (void *) to pass

Reading through the pthread tutorial from LLNL I hit the following example code

/******************************************************************************
* FILE: hello.c
* DESCRIPTION:
*   A "hello world" Pthreads program.  Demonstrates thread creation and
*   termination.
* AUTHOR: Blaise Barney
* LAST REVISED: 08/09/11
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0;t<NUM_THREADS;t++){
     printf("In main: creating thread %ld\n", t);
     rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
     if (rc){
       printf("ERROR; return code from pthread_create() is %d\n", rc);
       exit(-1);
       }
     }

   /* Last thing that main() should do */
   pthread_exit(NULL);
}

I can see why the long is cast through void * (as if it's not and you pass a pointer to t the numbers printed out by the threads are garbled), my question is should this be considered kosher and always work? Or is this a quick hack to get the simplest possible example of threading working? Is this a standard C thing?

like image 988
tacaswell Avatar asked Dec 06 '25 02:12

tacaswell


1 Answers

No, it's not strictly kosher in terms of the ISO C standard since there's no guarantee that a pointer is wide enough to hold a long.

A kosher solution would be to pass a pointer to the long, either with one unique long per thread (such as one in an array) or having inter-thread communication (such as condition variables) between the creator thread and created thread so that the latter can make a copy before the former is allowed to change it for the next thread creation.

However, the fact that it's not strictly kosher doesn't mean it won't work in a specific implementation. Provided you can guarantee the the cast between void* and long won't lose any information, it will probably work fine.

From C11 6.3.2.3 Pointers (though it's largely unchanged from C99):

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

like image 179
paxdiablo Avatar answered Dec 08 '25 15:12

paxdiablo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!