Q:

passing a type casted pointer to pthread_join

I have an assignment where I'm using threads in C, and similar to a lot of people I got errors caused by pthread_join's second argument being of type void** , then after some research I figured out how type casting works.  Here's an example of what I'm talking about: 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

void *callback(void *arg){
    sleep(2);
    pthread_exit("done !! \n");
}

int main(){
  pthread_t th;
  void *val;

  pthread_create(&th, NULL, callback, NULL);
  pthread_join(th, &val);
  printf("%s", (char*)val);

  return EXIT_SUCCESS;
}

and this worked as expected, but then I got curious and tried to declare a char *val then pass the casted version of it to the pthread_join function, like this:
int main(){
  pthread_t th;
  char *val;

  pthread_create(&th, NULL, callback, NULL);
  pthread_join(th, (void*)&val);
  printf("%s", val);

  return EXIT_SUCCESS;
}

This worked fine, but I don't understand how the type casting works in this version of the code.  Can anyone explain this please ? 

A:

The first code is correct, and the 2nd code is incorrect.  You'll get away with that because the representations for char * and void * are most likely compatible. 
An explicit pointer cast in C almost always says: "I am going to do some really dirty tricks, trust me, I know better than you, dear compiler, what I am doing".  There are only 4 exceptions that come to mind where a cast is necessary and right:

casting to a character pointer or character/void pointer back to the original
casting a pointer to a struct to the pointer to the type of the initial member or vice versa
casting a pointer to an union having the original type as its member
casting a pointer to a function to another function pointer type

All other cases are asking for nasal demons.  Rule of thumb with casts is: "the less the better". 
Furthermore, the type expected by pthread_join is void ** and not void * as was produced by your cast, but the void * being a generic pointer is silently converted to the void ** expected by pthread_join.