1

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?

5
  • But you're masking it into a void *, it will run ok. Commented Jul 18, 2013 at 1:00
  • How does it work? we cannot cast a number to pointer right? Commented Jul 18, 2013 at 1:04
  • You can turn the number into a pointer, but when you try to take it back to a number, you're going to be in bad shape, depending on the architecture, you may run into issues. Commented Jul 18, 2013 at 1:08
  • C allows you to convert between pointer and integer as long as the pointer value can be held by the integer type. But, the result is implementation defined. If the pointer value is larger than what the integer type can hold, the result is undefined. Commented Jul 18, 2013 at 1:14
  • @user1762571 - You can cast any integer to void* but the other way around is dangerous, casting void* to int is not portable. On a 64bit architecture pointer is 64bit wide but int is only 32bits. 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. Commented Jul 18, 2013 at 1:14

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@xaxxon - Yes it is wrong and will lead to undefined behavior; I added a comment on OP's post just below yours at the same time. I just added this as an example code for other interested in playing around with it. :) Sorry should have mentioned this in the answer.
1

What (void *)100 means is take the integer value 100 and treat it as a pointer to some unspecified type of memory (i.e., (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 ints 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.

Comments

0

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 .

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.