Programming Pearls 中的 qsort 函数出错?

Posted

技术标签:

【中文标题】Programming Pearls 中的 qsort 函数出错?【英文标题】:Error in qsort function in Programming Pearls? 【发布时间】:2010-11-07 12:13:51 【问题描述】:

只是我还是Programming Pearls 中的这段代码是错误的(quicksort 需要 2 个 const void,不是吗?)如果是这样,我的解决方案对吗?抱歉,刚刚学习...

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);

这是一个解决方案吗?

int sortcmp(const void *p, const void *q)
   return wordncmp(* (char * const *) p, * (char * const *) q);

【问题讨论】:

【参考方案1】:

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

正如你所说,qsort() 的最后一个参数是一个指向函数的指针,该函数采用两个 const void* 类型的参数。 sortcmp 采用不同的参数。你的编译器应该给你一个关于不兼容类型签名或其他东西的警告。在任何情况下,都是从一种类型的函数到另一种类型的函数执行转换。

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

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

但是,由于几乎在所有架构上,char **const void* 的表示方式都相同,因此函数调用几乎总是有效。

如果您想获得已定义的行为,您必须确保您的比较器函数具有正确的类型签名,然后您可以将参数转换为正确的类型。您的解决方案是完全正确的,并且没有违反那里的 C 标准。 const-correctness 做得很好——很多人不明白 char * const * 的确切含义。

您还应该让wordncmp() 接受const char* 的参数,因为您没有修改参数。

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

【讨论】:

该标准实际上不能保证char *void * 具有相同的表示吗?我同意使用错误的函数指针类型进行调用仍然是 UB,但我不认为参数的表示是问题所在。相反,问题在于病态实现可以使用不同的调用约定来传递void *char *,例如每种类型都有一组单独的参数寄存器。 @R.:是的,标准保证 char*void* 具有相同的表示和对齐要求(C99 §6.2.5/27),但 char**void*不一定兼容。【参考方案2】:

你是对的,sortcmp 的签名与qsort 的预期不匹配。你的更正是对的。 wordcmp 也应该设为 const-正确,因为从技术上讲,您在此过程中会失去一些 const-ness。

int wordncmp(const char *p, const char* q)

【讨论】:

以上是关于Programming Pearls 中的 qsort 函数出错?的主要内容,如果未能解决你的问题,请参考以下文章

《Programming Pearls》二分查找帮助

为 Python 查找最长重复字符串的有效方法(来自 Programming Pearls)

用 1 MB 空间对 1000 万个整数进行排序解决方案解释 - Programming Pearls

markdown [批量提取SDSS目录的SQL查询] #sdss #sherlock #catalogue #star #galaxy #qso

HDU 5090 Game with Pearls

hdu 1300 Pearls(dp)