1 of 3

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".