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?