关于作为参数传递给 qsort() 函数的比较函数的问题
Question concerning the comparison function passed as a parameter to the qsort() function
我正在学习 Coursera 的专业知识,在一节课中它解释了对给定数组进行排序的 qsort() 函数:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
我们应该为 qsort() 提供四个参数——要排序的数组、数组中元素的数量、数组中每个元素的大小,以及指向函数 (compar) 的指针,该函数接受两个 const void *s 和 returns 一个整数。课程说我们需要编写 compar
函数以与 qsort
函数兼容,因此如果我们想比较两个字符串,函数应该如下所示:
int compareStrings(const void * s1vp, const void * s2vp) {
// first const: s1vp actually points at (const char *)
// second const: cannot change *s1vp (is a const void *)
const char * const * s1ptr = s1vp;
const char * const * s2ptr = s2vp;
return strcmp(*s1ptr, *s2ptr);
}
void sortStringArray(const char ** array, size_t nelements) {
qsort(array, nelements, sizeof(const char *), compareStrings);
}
它说:请注意,传入的指针是指向数组中元素的指针(也就是说,它们指向数组中的框),即使这些元素本身就是指针(因为它们是字符串)。 当我们从 void *s 转换它们时,我们必须注意将它们转换为正确的类型——这里是 const char * const *— 并适当地使用它们,否则我们的功能将以某种方式被破坏。例如,考虑以下损坏的代码:
// BROKEN DO NOT DO THIS!
int compareStrings(const void * s1vp, const void * s2vp) {
const char * s1 = s1vp;
const char * s2 = s2vp;
return strcmp(s1, s2);
}
我不太明白的是为什么我们不把s1vp 和s2vp 当作指向指针的指针?我的意思是,由于传递给函数 compareStrings
的参数是指向字符串的指针地址(指针地址),我们不应该将 s1vp 和 s2vp 声明为 int compareStrings(const void ** s1vp, const void ** s2vp)
因为它们正在接收指针地址?
换句话说,例如,我正在将字符串数组的第一个元素的地址(实际上是一个指针)传递给 s1vp。所以现在 s1vp 正在接收指针的地址而不是变量,所以我们应该将它声明为指向指针的指针,对吗?当我尝试这样做时它会给我警告...
一个void *
可以指向任何数据类型。所讨论的数据类型也是指针这一事实并没有改变任何事情。
此外,您不能更改比较函数的签名,否则它将与 qsort
的预期不兼容,并可能导致 undefined behavior.