《Programming Pearls》中的 qsort 函数出错?

发布于 2024-07-26 09:11:29 字数 647 浏览 5 评论 0原文

是我一个人还是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);
}

is it just me or this code in Programming Pearls is wrong (quicksort wants 2 const voids, no?) If so, is my solution right? Apologies, just learning...

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

Is this a solution?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薄荷→糖丶微凉 2024-08-02 09:11:29

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

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

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

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

然而,由于实际上在所有体系结构上,char **const void* 都以相同的方式表示,因此函数调用几乎总是有效。

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

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

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

The first code sample will probably work with virtually any compiler and CPU; however, it is technically undefined behavior, if you follow the C standard to the letter.

As you said, the last argument to qsort() is a pointer to a function taking two arguments of type const void*. sortcmp takes different arguments. Your compiler should give you a warning about incompatible type signatures or something. In any case, a cast is being performed from a function of one type to a function of another type.

The C standard specifies that you can cast function pointers to other function pointers with different types, but you cannot dereference and invoke the casted function pointer. However, if you re-cast the function pointer back to its original type, then calling that has defined behavior -- it calls the original function.

Since you're casting from a int (*)(char**, char**) to a int (*)(const void*, const void*), and then eventually qsort() is invoking your comparator function without casting it back to int (*)(char**, char**), that's undefined behavior.

However, since virtually on all architectures, a char ** and a const void* are represented the same way, the function call will pretty much always work.

If you want to get defined behavior, you have to make sure your comparator function has the proper type signature, and then you can cast the arguments to the proper type. Your solution is exactly correct and does not violate the C standard there. Well done on const-correctness -- a lot of people don't understand exactly what char * const * means.

You should also make wordncmp() take parameters of const char*, since you're not modifying the parameters.

Side note: You also technically can't cast a function pointer to a data pointer (e.g. a void*) or vice-versa. The standard allows for function pointers and data pointers to have different sizes. Even if it works on your computer, it's not guaranteed to always work.

美煞众生 2024-08-02 09:11:29

您是对的,sortcmp 的签名与 qsort 期望的不匹配。 你的修正是正确的。 wordcmp 也应该是 const 正确的,因为从技术上讲,您在此过程中失去了一些 const 特性。

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

You are correct, the signature for sortcmp does not match what qsort expects. Your correction is right. wordcmp should also be made const-correct as you are technically losing some of the const-ness along the way.

int wordncmp(const char *p, const char* q)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文