title: Why can't I cast a function pointer to (void *)?
body: <p>I have a function that takes a string, an array of strings, and an array of pointers, and looks for the string in the array of strings, and returns the corresponding pointer from the array of pointers.  Since I use this for several different things, the pointer array is declared as an array of (void *), and the caller should know what kind of pointers are actually there (and hence what kind of a pointer it gets back as the return value).</p>
  
  <p>When I pass in an array of function pointers, however, I get a warning when I compile with <code>-Wpedantic</code>:</p>
  
  <p>clang:</p>
  
  <pre><code>test.c:40:8: warning: assigning to 'voidfunc' (aka 'void (*)(void)') from 'void *' converts
        between void pointer and function pointer [-Wpedantic]
  </code></pre>
  
  <p>gcc:</p>
  
  <pre><code>test.c:40:8: warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
     fptr = find_ptr("quux", name_list, (void **)ptr_list,
  </code></pre>
  
  <p>Here's a test file, which despite the warning does correctly print "quux":</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  
  void foo(void)
  {
    puts("foo");
  }
  
  void bar(void)
  {
    puts("bar");
  }
  
  void quux(void)
  {
    puts("quux");
  }
  
  typedef void (* voidfunc)(void);
  
  voidfunc ptr_list[] = {foo, bar, quux};
  
  char *name_list[] = {"foo", "bar", "quux"};
  
  void *find_ptr(char *name, char *names[], void *ptrs[], int length)
  {
    int i;
  
    for (i = 0; i &lt; length; i++) {
      if (strcmp(name, names[i]) == 0) {
        return ptrs[i];
      }
    }
    return NULL;
  }
  
  int main() {
    voidfunc fptr;
  
    fptr = find_ptr("quux", name_list, (void **)ptr_list,
                    sizeof(ptr_list) / sizeof(ptr_list[0]));
    fptr();
  
    return 0;
  }
  </code></pre>
  
  <p>Is there any way to fix the warning, other than not compiling with <code>-Wpedantic</code>, or duplicating my find_ptr function, once for function pointers and once for non-function pointers?  Is there a better way to achieve what I'm trying to do?</p>