`p1` (and `p2` too) is `const void *` and it comes from a `const char **` (for legacy reasons, argv is not `const` but should be treated as if it were). That means, the ultimate `char` is `const`: "a pointer to a pointer to a const char". Let's see what is going on before the fix first, and then the fix. Before the fix: `(char *const *)` (I removed the space on purpose) casts `p1` to be "a pointer to a const pointer to a non-const char". That's clearly not what it originally was. Then we dereference, ending with a `char *const`, which is "a const pointer to a non-const char". But given that the pointer value is passed to a function, `const` doesn't make sense there, because the function will already take a copy of it, so it is impossible to modify the pointer itself. The fix: `(const char **)` The only thing that is const is the ultimate `char`, which is the only thing that matters, because it is the only thing strcmp(3) has access to (everything else, i.e. the pointers, are copies). Then, after the dereference we end up with `const char *`, the type of argv (more or less, as previously noted), which is also the type of the arguments to strcmp(3). Signed-off-by: Alejandro Colomar <colomar.6.4.3@xxxxxxxxx> --- man3/qsort.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man3/qsort.3 b/man3/qsort.3 index e1af43cf0..24f0b6c92 100644 --- a/man3/qsort.3 +++ b/man3/qsort.3 @@ -137,7 +137,7 @@ cmpstringp(const void *p1, const void *p2) pointers to char", but strcmp(3) arguments are "pointers to char", hence the following cast plus dereference */ - return strcmp(* (char * const *) p1, * (char * const *) p2); + return strcmp(*(const char **) p1, *(const char **) p2); } int -- 2.28.0