简体   繁体   中英

pthread_create argument in c multi thread programming

pthread_create(&Thread,NULL,ChildThread,(void *)100);

1) Can we pass the 4th argument of pthread_create as shown above? shouldn't it be a pointer variable?

Just an example ( not meant to be correct way of doing it; but to serve as example code for anyone who want to play with it ):

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>

void *print_number(void *number) {
    printf("Thread received parameter with value: %d\n", number);
    return (void *)number;
}

int main(int argc, char *argv[]) {
    pthread_t thread;
    void *ret;
    int pt_stat;
    pt_stat = pthread_create(&thread, NULL, print_number, (void *)100);
    if (pt_stat) {
        printf("Error creating thread\n");
        exit(0);
    }

    pthread_join(thread, &ret);
    printf("Return value: %d\n", ret);

    pthread_exit(NULL);

    return 0;
}

This will lead to undefined behavior if the pointer value is greater then what an int can hold. See this quote from C99:

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.

What (void *)100 means is take the integer value 100 and treat it as a pointer to some unspecified type of memory (ie, (void *) ). In that case, that means push the integer value 100 on the stack as an argument to pthread_create . Presumably, ChildThread casts the void * passed to it back to an int , then uses it as a number.

Fundamentally pointers are really just memory addresses. A memory address is just a number that describes a location in memory, so casting an int to a pointer of any type is legal. There are a few cases where casting an int to a pointer is absolutely the right thing to do and required, however, they tend to be rare. For example, if you are writing code for an embedded controller, and want write a driver for a memory mapped I/O device, then you might cast the device's base address as a pointer to an int or struct and then do normal C accesses through the pointer to access the device. Another example where casting int s to pointers, would be to implement the low-level virtual memory management routines to parcel out physical memory for an operating system.

The code you present is not uncommon and will work, assuming that the size of a pointer is at least big enough to hold the integer you are trying to pass. Most systems that implement pthread_create would probably have a 32-bit or 64-bit pointer, so your example is pretty likely to work. IMHO, it is a bit of an abuse, because 100 probably does not refer to a memory location in this case, and C does not guarantee that a void * is big enough to hold an int .

Taken from an excellent artice on POSIX Thread Progreamming . Must read for any newbie .

Example Code - Pthread Creation and Termination

#include <pthread.h>
#include <stdio.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);
}

Explanation :

You can pass the 100 as the 4th argument to the pthread_create() . In the function PrintHello you can typecast the void* back into the correct type .

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