编程珍珠中的qsort函数出错?

Der*_*unk 4 c std qsort programming-pearls

编程珍珠只是我或者这个代码是错误的(quicksort想要2个const空洞,不是吗?)如果是这样,我的解决方案是对的吗?道歉,只是学习......

int wordncmp(char *p, char* q)
{   int n = k;
    for ( ; *p == *q; p++, q++)
        if (*p == 0 && --n == 0)
            return 0;
    return *p - *q;
}

int sortcmp(char **p, char **q)
{   return wordncmp(*p, *q);
}
...

qsort(word, nword, sizeof(word[0]), sortcmp);
Run Code Online (Sandbox Code Playgroud)

这是一个解决方案吗?

int sortcmp(const void *p, const void *q)
{   return wordncmp(* (char * const *) p, * (char * const *) q);
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*eld 7

第一个代码示例可能几乎适用于任何编译器和CPU; 但是,如果您遵循C标准,那么这是技术上未定义的行为.

正如你所说,最后一个参数qsort()是指向一个带有两个类型参数的函数的指针const void*. sortcmp采取不同的论点.您的编译器应该向您发出有关不兼容类型签名的警告.在任何情况下,正在从一种类型的功能到另一种类型的功能执行转换.

C标准指定您可以将函数指针强制转换为具有不同类型的其他函数指针,但是您不能取消引用并调用已转换的函数指针.但是,如果将函数指针重新转换回其原始类型,则调用已定义的行为 - 它将调用原始函数.

由于你是从a转换int (*)(char**, char**)为a int (*)(const void*, const void*),然后最终qsort()调用你的比较器函数而不将其转换回来int (*)(char**, char**),这是未定义的行为.

但是,由于几乎在所有体系结构上,a char **和a const void*以相同的方式表示,因此函数调用几乎总是有效.

如果要获得已定义的行为,则必须确保比较器函数具有正确的类型签名,然后可以将参数转换为正确的类型.您的解决方案完全正确,并且不违反C标准.做得好const- 正确性 - 很多人都不明白究竟是什么char * const *意思.

您还应该制作wordncmp()参数const char*,因为您没有修改参数.

旁注:您在技术上也不能将函数指针强制转换为数据指针(例如a void*),反之亦然.该标准允许函数指针和数据指针具有不同的大小.即使它在您的计算机上运行,​​也不能保证始终有效.