The fact that you can use a wrapper to avoid the warning should show that there isn't a deep technical reason:

    void bar(const char *p) { /* ... */ }
    void bar_w(char *p) { bar(p); }  /* wrapper */

    foo(bar_w);  /* instead of foo(bar) */

This is based on then well known fact that you can use a *pointer-to-T* (for any type T) where a *pointer-to-const-T* is expected (as in your first example).

The warning is due to *§6.7.5.3.15 - Function declarators* (from ISO/IEC 9899:TC3):

> For two function types to be compatible...
>
> [cut]
>
> Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; **corresponding parameters shall have compatible types**.

and `const char *p` is not compatible with `char *p`.

Anyway the compiler issues just a warning (not an error): maybe the programmer is using the wrong function (with a similar signature) and the warning can help to identify the situation.

If everything is ok an explicit cast / a wrapper function can rapidly resolve the "nuisance".

---
EDIT

> it appears that `char *p` is compatible with `const char *p`, just not the other way around

`char *p` can be **implicitly converted** to `const char *p` (§6.3.2.3):

> For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal

(in other words, `const`, `volatile` and `restrict` qualifiers can be added. The original pointer and the result compare equal. See also [Implicit conversions][1]).

E.g.

    char n;
    const char *p = &n;  /*   &n has type char *   */

This doesn't mean that `const char *` (a pointer to const-qualified char) is **compatible** with `char *` (pointer to char):

> For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types

<sup>(§6.7.5.1)</sup>

The pointer are identically qualified (they aren't qualified!) but they aren't pointer to compatible types (`const char` is not compatible with a `char`).



  [1]: http://en.cppreference.com/w/c/language/conversion