Chr*_*is 6 c syntax function-pointers qsort
这来自我正在使用的"神奇"数组库.
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);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:究竟什么是qsort做的最后一个论点?
(int (*)(const void *, const void*))compare)
Run Code Online (Sandbox Code Playgroud)
qsort采用int (*comp_fn)(const void *,const void *)比较器参数,但此sort函数采用带双指针的比较器.不知何故,上面的行将双指针版本转换为单指针版本.有人可以解释一下吗?
这正是你引用的演员:它转换了一个类型的指针
int (*)(const void **, const void **)
Run Code Online (Sandbox Code Playgroud)
指向类型的指针
int (*)(const void *, const void *)
Run Code Online (Sandbox Code Playgroud)
后者是预期的qsort.
这样的事情经常遇到质量差的代码.例如,当有人想要对ints 数组进行排序时,他们通常会编写一个接受指针的比较函数int *
int compare_ints(const int *a, const int *b) {
return (*a > *b) - (*a < *b);
}
Run Code Online (Sandbox Code Playgroud)
当实际调用时,qsort他们强行将其强制转换为适当的类型以抑制编译器的抱怨
qsort(array, n, sizeof *array, (int (*)(const void *,const void *)) compare_ints);
Run Code Online (Sandbox Code Playgroud)
这是一个"黑客",导致未定义的行为.显然,这是一种不好的做法.你在你的例子中看到的只是同一个"hack"的一个不那么直接的版本.
在这种情况下,正确的方法是将比较函数声明为
int compare_ints(const void *a, const void *b) {
int a = *(const int *) a;
int b = *(const int *) b;
return (a > b) - (a < b);
}
Run Code Online (Sandbox Code Playgroud)
然后在没有任何演员的情况下使用它
qsort(array, n, sizeof *array, compare_ints);
Run Code Online (Sandbox Code Playgroud)
通常,如果人们希望他们的比较函数用作qsort(和类似函数)中的比较器,则应该使用const void *参数来实现它们.
在大多数硬件上,您可以假设指针在硬件级别上看起来都是相同的。例如,在具有平面 64 位寻址指针的系统中,指针将始终是 64 位整数。对于指针到指针或指针到指针到指针的指针也是如此。
因此,无论使用什么方法来调用带有两个指针的函数,都适用于任何带有两个指针的函数。指针的具体类型并不重要。
qsort一般地对待指针,就好像每个指针都是不透明的一样。所以它不知道也不关心它们是如何取消引用的。它知道它们当前的顺序,并使用比较参数来计算出它们应该采用的顺序。
您正在使用的库大概保留了指向相关指针的指针列表。它有一个比较函数,可以比较两个指针与指针。因此它会将其传递给 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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
968 次 |
| 最近记录: |