The problem is that the pointer is set to a local variable. So when the function terminates, it's memory will be de-allocated, thus the pointer will be set to garbage (it will become a dangling pointer as Hans suggested).
So if you are lucky, the printf() will print garbage, if not, then it will print 5.
A quick fix would be to add the static keyword to int a, which make it not to be de-allocated when the function gets terminated.
void fun(void** val) {
  static int a = 5;
  *val = &a;
}
However this is not very flexible, because all the instances of fun() will have the same variable a.
Or you could dynamically allocate memory like this:
void fun(void** val) {
  int *a = malloc(sizeof(int));
  *a = 5;
  *val = a;
}
Don't forget to free your memory like this:
  a_t *x;
  x = malloc (sizeof *x);
  fun (&x->val);
  printf ("%d", *((int*)(x->val)));
  free(x->val);  // this has to go first
  free(x);
  return 0;
}