在Mac和Linux上qsort_r的不同声明 [英] Different declarations of qsort_r on Mac and Linux

查看:97
本文介绍了在Mac和Linux上qsort_r的不同声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们看看Linux(/usr/include/stdlib.h)中的函数qsort_r:

Let's see function qsort_r in Linux (/usr/include/stdlib.h):

typedef int (*__compar_d_fn_t)(const void *, const void *, void *);

extern void qsort_r (void *__base, size_t __nmemb, size_t __size,
         __compar_d_fn_t __compar, void *__arg)
  __nonnull ((1, 4));

让我们看看Mac(/usr/include/stdlib.h)中的功能qsort_r:

Let's see function qsort_r in Mac (/usr/include/stdlib.h):

void qsort_r(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *));

如您所见,这些声明彼此不同(参数顺序).这真是令人惊讶!抱怨解决这个问题会有效吗?

As you can see these declarations are differ from each other (sequence of arguments). This is surprising! Will it be effective to complain somewhere to solve this problem?

推荐答案

在某个地方抱怨以解决此问题是否有效?

Will it be effective to complain somewhere to solve this problem?

A,不.这种方式已经存在了太长时间,并且有太多的代码依赖于此.

Alas, no. It's been this way for too long and there's too much code relying on it.

我认为根本的问题是"为什么会发生这些不兼容性"?我会回答.它似乎可以归结为BSD首先实现它,但界面较差. ISO和更高版本的GNU修复了该接口,并认为兼容性破坏值得这样做.微软会做任何他们想做的事.

I think the underlying question is "why do these incompatibilities happen"? I'll answer that. It appears to boil down to BSD implementing it first but with a poor interface. ISO and later GNU fixed the interface and decided the compatibility breakage was worth it. And Microsoft does whatever they feel like.

如@Downvoter(大名)所指出的那样,qsort_r是非标准函数.如果它是标准的,那就太好了,但是您不能依靠它. qsort_s是C11附件K中的一种标准,但是没有人真正实现C11,更不用说其附件了,

As pointed out by @Downvoter (great name), qsort_r is a non-standard function. It would be nice if it were standard, but you can't rely on that. qsort_s is sort of standard in C11 Annex K, but nobody really implements C11, let alone its annexes, and whether Annex K is a good idea is in question.

与许多C和Unix问题一样,这归结为BSD,GNU和Microsoft以及它们无法协调C扩展. Linux是GNU. OS X杂乱无章,但对于C而言,它遵循BSD.

Like a lot of C and Unix issues, this comes down to BSD vs GNU vs Microsoft and their inability to coordinate C extensions. Linux is GNU. OS X is a mish-mash of many things, but for C it follows BSD.

FreeBSD在2002年9月添加了qsort_r.VisualStudio 2005具有稍微不同的qsort_s. ISO在2007年再次将qsort_s正式化.终于,几年后,GNU终于在2008年出现在glibc 2.8中,显然是在遵循ISO. 这是一个跨越2004年到2008年的旧线程,要求在glibc中实现qsort_r 有一些道理.

FreeBSD added qsort_r in Sept 2002. Visual Studio 2005 featured a slightly different qsort_s. ISO formalized a yet different again qsort_s in 2007. Finally GNU's came years later in glibc 2.8 in 2008 apparently following ISO. Here's an old thread spanning 2004 to 2008 requesting qsort_r be implemented in glibc which has some rationales.

提醒大家,这是C99中定义的qsort.

For remind everyone, here is qsort as defined in C99.

void qsort(
    void *base, size_t nmemb, size_t size,
    int (*compar)(const void *, const void *)
);


FreeBSD是2002年9月的第一个.他们决定qsort_r应该打破qsort接口,并将"thunk"自变量放在比较函数之前.


FreeBSD was the first in Sept 2002. They decided that qsort_r should break the qsort interface and put the "thunk" argument before the comparison function.

void qsort_r(
    void *base, size_t nmemb, size_t size,
    void *thunk,
    int (*compar)(void *, const void *, const void *)
);

为什么?您必须要问 Garrett Wollman 是谁写了补丁.查看补丁,您可以从他对CMP的更改中看到,首先,重击"是一个很好的模式.也许他们认为比较功能要走到最后"是人们会记住的.不幸的是,这意味着qsortqsort_r的比较函数的参数颠倒了.非常令人困惑.

Why? You'll have to ask Garrett Wollman who wrote the patch. Looking at the patch you can see from his changes to CMP it was decided that having the "thunk" first was a good pattern. Maybe they decided "the comparison function goes at the end" was what people would remember. Unfortunately this means qsort and qsort_r's comparison functions have their arguments reversed. Very confusing.

与此同时,曾经是创新者的微软 qsort_s在Visual Studio 2005中.

Meanwhile Microsoft, ever the innovator, has qsort_s in Visual Studio 2005.

void qsort_s(
   void *base, size_t num, size_t width,
   int (__cdecl *compare )(void *, const void *, const void *),
   void * context
);

"s"代表安全",而不是"r"代表可重入",其他人可能都遵循ISO约定(请参阅下文),反之亦然.他们将"thunk"放在qsort_s的末尾,使参数与qsort相同,但是为了最大程度地混淆,"thunk"在比较功能(如BSD)的开始处进行.他们选择了最糟糕的选择.

"s" for "secure" rather than "r" for "reentrant" that everyone else was using possibly following an ISO convention (see below) or vice-versa. They put the "thunk" at the end of qsort_s, keeping the arguments the same as qsort, but for maximum confusion the "thunk" goes at the start of the comparison function like BSD. They chose the worst possible option.

更糟糕的是,ISO在2007年发布了 TR 24731-1 将边界检查添加到C标准库中(感谢@JonathanLeffler指出了这一点).是的,他们有自己的qsort_r,但它称为qsort_s!是的,它不同于其他所有人!

To make matters worse, in 2007 ISO published TR 24731-1 to add bounds checking to the C standard library (thanks @JonathanLeffler for pointing that out). And yes, they have their own qsort_r, but it's called qsort_s! And yes, it's different from everyone else's!

errno_t qsort_s(
    void *base, rsize_t nmemb, rsize_t size,
    int (*compar)(const void *x, const void *y, void *context),
    void *context
);

他们明智地决定将qsort_s的参数及其比较函数保留为qsort的超集,可能是认为这样会使人们更容易记住.他们添加了一个返回值,这可能是一个好主意.更令人困惑的是,当时这是技术报告",不是C标准的一部分.现在是C11标准的附件K",仍然是可选的,但重量更大.

They wisely decided to keep the arguments to qsort_s and its comparison function a superset of qsort probably arguing it would be easier for people to remember. And they added a return value, probably a good idea. To add to the confusion, at the time this was a "Technical Report" and not part of the C standard. It's now "Annex K" of the C11 standard, still optional but carries more weight.

GNU做出了相同的决定,可能是遵循ISO的qsort_s.

GNU decided the same, possibly following ISO's qsort_s.

void qsort_r(
    void *base, size_t nmemb, size_t size,
    int (*compar)(const void *, const void *, void *),
    void *arg
);

查看添加了qsort_r的glibc补丁它可能也更容易实现.要确定要知道,您必须询问Ulrich Drepper.

Looking at the glibc patch adding qsort_r it was probably also easier to implement. To know for sure you'll have to ask Ulrich Drepper.

多年来,BSD决定与qsort交换参数的决定及其比较功能可能引起了很多混乱和错误. ISO/GNU决定使它们保持相同的决定可以说是更好的选择. ISO决定给它起一个不同的名字. GNU决定破坏与BSD功能的兼容性.微软决定做任何事情.现在,我们陷入了四个不兼容的实现中.由于比较函数具有不同的签名,因此兼容性宏是不平凡的.

BSD's decision to swap arguments with qsort and its comparison function has probably caused a lot of confusion and bugs over the years. The ISO / GNU decision to keep them the same is arguably better. ISO decided to give it a different name. GNU decided to break compatibility with the BSD function. Microsoft decided to do whatever. Now we're stuck with four incompatible implementations. Because the comparison functions have different signatures a compatibility macro is non-trivial.

(这都是对代码的重新构造.出于其实际原理,您必须深入研究邮件列表档案.)

(This is all a reconstruction from the code. For their actual rationales you'll have to dig through mailing list archives.)

我不能真正责怪GNU或BSD或ISO或Microsoft ...好吧,我可以责怪Microsoft故意杀死C.Point是标准化C,扩展该标准并促使编译器遵循的过程该标准非常缓慢,并且编译器编写者有时不得不做权宜之计.

I can't really blame GNU or BSD or ISO or Microsoft... ok, I can blame Microsoft for deliberately trying to kill C. Point is the process of standardizing C, and extending that standard, and getting compilers to follow that standard is painfully slow and the compiler writers sometimes have to do what's expedient.

这篇关于在Mac和Linux上qsort_r的不同声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆