这个C语法是什么意思?

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函数采用带双指针的比较器.不知何故,上面的行将双指针版本转换为单指针版本.有人可以解释一下吗?

AnT*_*AnT 8

这正是你引用的演员:它转换了一个类型的指针

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 *参数来实现它们.


Tom*_*mmy 2

在大多数硬件上,您可以假设指针在硬件级别上看起来都是相同的。例如,在具有平面 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)