这是我正在使用的“神奇”数组库。
void
sort(magic_list *l, int (*compare)(const void **a, const void **b))
{
qsort(l->list, l->num_used, sizeof(void*),
(int (*)(const void *,const void *))compare);
}
我的问题是:究竟什么是qsort做的最后一个论点?
(int (*)(const void *, const void*))compare)
qsort将int (*comp_fn)(const void *,const void *)
作为比较器参数,但此sort函数采用带双指针的比较器。不知何故,上面的行将双指针版本转换为单指针版本。有人可以帮忙解释一下吗?
答案 0 :(得分:8)
这正是你引用的演员:它转换了一个
类型的指针int (*)(const void **, const void **)
指向
类型的指针int (*)(const void *, const void *)
后者是qsort
所期望的。
这样的事情经常遇到质量差的代码。例如,当有人想要对int
的数组进行排序时,他们通常会编写一个比较函数来接受指向int *
的指针
int compare_ints(const int *a, const int *b) {
return (*a > *b) - (*a < *b);
}
当实际调用qsort
时,他们强制将其强制转换为正确的类型以抑制编译器的投诉
qsort(array, n, sizeof *array, (int (*)(const void *,const void *)) compare_ints);
这是一个“黑客”,导致未定义的行为。显然,这是一种不好的做法。你在你的例子中看到的只是同一个“黑客”的一个不太直接的版本。
在这种情况下,正确的方法是将比较函数声明为
int compare_ints(const void *a, const void *b) {
int a = *(const int *) a;
int b = *(const int *) b;
return (a > b) - (a < b);
}
然后在没有任何演员阵容的情况下使用它
qsort(array, n, sizeof *array, compare_ints);
一般来说,如果人们希望他们的比较函数在qsort
(和类似的函数)中用作比较器,那么应该用const void *
参数来实现它们。
答案 1 :(得分:3)
qsort的最后一个参数是将一个带有双指针的函数指针转换成一个接受qsort接受的单指针的指针。它只是一个演员。
答案 2 :(得分:2)
在大多数硬件上,您可以假设指针在硬件级别看起来都相同。例如,在具有平坦64位寻址指针的系统中,指针总是64位整数。指向指针的指针或指向指针指针的指针也是如此。
因此,无论使用何种方法调用具有两个指针的函数,都可以使用任何带有两个指针的函数。指针的具体类型无关紧要。
qsort
一般地处理指针,好像每个都是不透明的。所以它不知道或不关心它们如何被解除引用。它知道它们当前处于什么顺序,并使用compare参数来确定它们应该处于什么顺序。
您正在使用的库可能会保留指向指针的列表。它有一个比较函数,可以比较两个指针指针。因此它将其转换为传递给qsort。它在语法上比例如
更好qsort(l->list, l->num_used, sizeof(void*), compare);
/* elsewhere */
int compare(const void *ptr1, const void *ptr2)
{
// these are really pointers to pointers, so cast them across
const void **real_ptr1 = (const void **)ptr1;
const void **real_ptr2 = (const void **)ptr2;
// do whatever with real_ptr1 and 2 here, e.g.
return (*real_ptr2)->sort_key - (*real_ptr1)->sort_key;
}
答案 3 :(得分:1)
它正在转换函数指针。我想原因是比较可以应用于被解除引用的指针而不是它们指向的任何指针。
答案 4 :(得分:0)
(int (*)(const void *,const void *))compare
是一个C样式转换,用于将函数指针compare
强制转换为带有两个const void *
args的函数指针。
答案 5 :(得分:0)
最后一个参数是一个函数指针。它指定它接受一个指向函数的指针,该函数返回一个int并带有两个const void **
参数。