qsort的第4个参数的"不兼容的指针类型"编译器警告

chr*_*yss 4 c sorting pointers casting widechar

我正在尝试使用标准库qsort来排序宽字符数组:

wchar_t a = L'a';
wchar_t a1 = L'ä';
wchar_t b = L'z';
wchar_t chararray[] = {b, a, a1};  
length = wcslen(chararray);

qsort(chararray, length, sizeof(wchar_t), wcscoll);
Run Code Online (Sandbox Code Playgroud)

现在我认为所涉及的功能有这些原型:

int wcscoll(const wchar_t *ws1, const wchar_t *ws2);
void qsort(void *base, size_t num, size_t size, int (*comp_func)(const void *, const void *))
Run Code Online (Sandbox Code Playgroud)

结果完全符合预期,但为什么我得到编译器警告" passing argument 4 of ‘qsort’ from incompatible pointer type"?我怎么能投射wcscoll以适应原型?

如果我定义并传入一个单独的比较函数,警告就会消失:

int widecharcomp(const void *arg1, const void *arg2)
{
    return wcscoll(arg1, arg2);
}
Run Code Online (Sandbox Code Playgroud)

...但是当参数不是类型时,这个看起来应该有错误处理wchar_t *.

Tyl*_*nry 8

你已经做了很多正确的方法. 海湾合作委员会的文件strcoll,并wcscoll提供了一种类似于此为正确的使用方法的例子strcoll或wcscoll用qsort.

 /* This is the comparison function used with qsort. */

 int
 compare_elements (char **p1, char **p2)
 {
   return strcoll (*p1, *p2);
 }

 /* This is the entry point---the function to sort
    strings using the locale's collating sequence. */

 void
 sort_strings (char **array, int nstrings)
 {
   /* Sort temp_array by comparing the strings. */
   qsort (array, nstrings,
          sizeof (char *), compare_elements);
 }
Run Code Online (Sandbox Code Playgroud)

这个例子实际上没有提高,你想摆脱的警告,但同样也可以通过改变得到解决,char**以const void*在参数compare_elements,然后明确地铸造const char**.

你是正确的观察到这种类型不安全,但类型安全并不是C的优点之一.C没有类似泛型或模板的东西,所以qsort可以在任意类型上工作的唯一方法是它的比较函数接受void*s.程序员可以确保比较函数不会在可能传递非预期类型的​​参数的上下文中使用.

也就是说,代码中存在错误.比较函数接收的不是要比较的元素,而是指向要比较的元素的指针.因此,如果元素是字符串,那意味着指向指针.所以当你写作

return wcscoll(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)

你实际上正在通过wscoll一个wchar_t**它预期的时间wchar_t*.在抑制警告的同时执行此操作的正确方法是:

int widecharcomp(const void *arg1, const void *arg2)
{
    return wcscoll(*(const w_char_t**)arg1, *(const w_char_t**)arg2);
}
Run Code Online (Sandbox Code Playgroud)

像那样丑陋.

编辑:

再看一下代码的最高位.你的错误在这里真是双重的.你正试图wcscoll用来对字符进行排序.它是一个用于排序字符串的函数(在C中是指向以空字符结尾的字符序列的指针).上面的内容是假设您尝试对字符串进行排序而编写的.如果要对字符进行排序,wcscoll则不适合使用,但上述所有内容qsort仍然适用.