1
void print_hello_world() {
    pid_t pid = getpid();
    printf("Hello world %d\n", pid);
    pthread_exit(0);
}

void main() {
    pthread_t thread;
    pthread_create(&thread, NULL, (void *) &print_hello_world, NULL);
    print_hello_world();
}

I really couldn't understand what is the need of (void *) in pthread_create. And do we need "&print_hello_world" in the same or could drop "&" as I have read somewhere that while passing function pointers we don't need to place "&" before the function name.

ElGavilan
  • 6,610
  • 16
  • 27
  • 36
UtkarshPramodGupta
  • 7,486
  • 7
  • 30
  • 54

2 Answers2

3

Yes, there's no need for cast or & operator there:

pthread_create(&thread, NULL, print_hello_world, NULL);

should suffice as a function name gets converted into a function pointer when passing as argument to function(s).

Note that the function pointer you pass to pthread_create() takes a void* as argument and returns a void *. So your function should be:

void* print_hello_world(void *unused) {
...
}

It's the C way of implementing "generic" data type. For example, you can pass a int* or struct args* to the thread function and retrieve it back. E.g.

 int i=5;
 pthread_create(&thread, NULL, print_hello_world, &i); 

and in the function print_hello_world(), you would do:

void *print_hello_world(void *value) {
  int i = *(int*)value;
  ... 
}

Basically void* allows you to pass any data pointer to the thread function here. If pthread_create()'s thread function were to take int*, you wouldn't be able to pass a struct args* to it, for example.

I suggest you read the following posts for more information on void pointer and its usage in C:

Concept of void pointer in C programming and What does void* mean and how to use it?

Community
  • 1
  • 1
P.P
  • 117,907
  • 20
  • 175
  • 238
  • What could void* possibly mean? As int* mean the return value is an integer pointer. void pointer makes no sense. :/ – UtkarshPramodGupta Aug 04 '15 at 13:23
  • Could you pls elaborate? I couldn't understand – UtkarshPramodGupta Aug 04 '15 at 13:31
  • @UtkarshGupta The comment was getting too big. Please see the updated the answer. – P.P Aug 04 '15 at 13:37
  • Couldn't we have casted the passed argument from (int*) to (struct*) or vice-versa, had that been the case? – UtkarshPramodGupta Aug 04 '15 at 14:39
  • @UtkarshGupta Casting `TYPE1 *` to `TYPE2 *` is not guaranteed to work for all types (except casting to a character type: `char *`, `unsigned char*` or `signed char*`). Using `void *` is the only portable way without worrying about aliasing. – P.P Aug 04 '15 at 14:42
  • Are you sure about that? – UtkarshPramodGupta Aug 04 '15 at 14:43
  • @Olaf I never said conversion between different pointer types is valid. OP asked "caste[d] the passed argument from from (int*) to (struct*) or vice-versa" and I replied to that. I don't get what you are trying to say. – P.P Aug 04 '15 at 18:04
  • @Olaf It's not about the the function pointer but the argument that the thread function takes and value it returns. I added one example with the argument it takes. The same is applicable to the return value too -- both are data pointers. There was no reference to function pointers in my comment. – P.P Aug 04 '15 at 18:20
  • Fair point! Sorry, I apparently missed the initial comment of Utkarsh. – too honest for this site Aug 04 '15 at 18:32
2

Casting a function pointer to/from void * is actually undefined behaviour. See 6.3.2.3, especially p1 and p8. Note that functions are no objects in C.

So the cast is wrong in fact and the addressof-operator & is unnecessary. You can cast, however, one function pointer to another (see §8 of the reference). But here, you shoud definitively have a proper signature for your function, as there is a reason it takes a pointer and returns one, too. So: do not cast, but get the signature (and semantics) correct.

Note: An empty identifier-list in a function declaration which is part of the definition is an obsolescent feature. Using the prototype-style (void) for an empty argument list is recommended. Also the minimal required signature for main is int main(void) (with respect to the above said).

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • 1
    Could you give a citation for the claim that a function with no arguments must be declared `[type] foo(void)`? Also, the real problem is that `pthread_create()` expects a pointer to a function with of type `void *(*)(void *)`. – EOF Aug 04 '15 at 16:37
  • @EOF: For `()` vs. `(void)` I was a bit overhasty; that is just to become obsolete in a future version (hopefully); i edited my text accordingly.Regarding the function pointer: [6.3.2.3§8](http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p8) actually covers that already. Oh, wait, I just noticed what you mean. Edited. – too honest for this site Aug 04 '15 at 17:46