我是C的初学程序员,想要习惯术语和指针。 我在寻找一种对数值数组元素进行排序的方法时,找到了以下工作函数原型。函数是qsort,它使用指针。现在我所理解的是,“const”这个词确保了值a和b不变,但指针却没有。如果我在这里错了,请纠正我。我的问题是:
void *
函数我们不能使用int *
开始? *(int*)a
如何
工作?为什么qsort算法需要这么多参数?
int compare (const void *a, const void *b)
{
return ( *(int*)a - *(int*)b );
}
非常感谢答案。 PS:对我来说,这是一项非常复杂的任务。
答案 0 :(得分:2)
qsort
以这种方式制作,因此可以用作通用分类器。如果它从一开始就使用int
,它只能用于比较整数。这样,您也可以通过将strcmp
作为比较函数传递给qsort
来对字符串进行排序。*(int*)a
将a
转换为指向int
的指针,然后取消引用它,以便获得存储在a
的整数。请注意,这不会更改a
或a
指向的值。 qsort
需要4个参数:要排序的数组,该数组中元素的数量以及元素的大小,最后是比较函数。它需要所有这些信息,因为它再次被认为是尽可能通用的。
它需要元素的数量,因为在C指针中不包含有关它们之后的缓冲区大小的信息。并且它需要知道每个元素的大小,以便它可以正确地将元素传递给比较函数。例如,要比较int
,您可以将sizeof(int)
作为尺寸参数。要比较字符串,请使用sizeof(char *)
。
ADDIT 使用const void *
的原因是指示比较函数可能不会更改a
和b
指向的值。当然,这是为了确保对数组进行排序不会突然改变数组中的值。而且,正如H2CO3所说的那样,投射到(const int *)
会更加清晰,这样你就不会在投射后不小心改变它:
return *(const int *)a - *(const int *)b;
你也可以通过以下方式摆脱演员阵容:
int compare(const void * a, const void * b){
const int * ia = a;
const int * ib = b;
return *ia - *ib;
}
取决于你对演员表的喜好。 (我更愿意避开它们)
最后,澄清星号:
*(int *)a
^ ^
| └ cast to integer pointer
└ dereference (integer) pointer
答案 1 :(得分:2)
你理解错了。现在我所理解的是" const"确保值
a
和b
不变,但指针
const int *a;
将a
声明为常量int
类型的指针。这意味着单词const
可确保您无法通过修改a
来修改变量*a
指向的值。
为什么我们使用void *函数我们从一开始就不能使用int *?
void *
用于指出任何类型的变量。
返回部分的构造
*(int*)a
如何工作?
*(int *)
用于将a
转换为指向int
的指针,然后取消引用它以获取存储在其指向的位置的值。
答案 2 :(得分:1)
其他答案非常好。我只想补充一点,如果你在回调函数中非常清楚,它会更容易阅读。
int compare (const void *a, const void *b)
{
return ( *(int*)a - *(int*)b );
}
变为
int compare (const void *a, const void *b)
{
int ia = *(int *)a;
int ib = *(int *)b;
return ia - ib;
}
在这种情况下,它并不太重要,但是当您的比较功能变得复杂时,您可能希望在进行比较之前将变量设置为“您的类型”。
由于您在下面的评论中提到过,这是一个非常循序渐进的版本:
int compare (const void *a, const void *b)
{
int *pa = (int *)a;
int *pb = (int *)b;
int ia = *pa;
int ib = *pb;
return ia - ib;
}
答案 3 :(得分:0)
qsort()
函数是泛型算法的一个示例,它是作为通用例程实现的。我们的想法是使其对排序任意对象很有用,而不仅仅是int
或float
。因此(并且由于C语言设计),qsort()
采用比较函数作为接受两个通用(在C意义上)指针的参数。该函数(由qsort()
用户提供)可以将这些指针强制转换为正确的类型,执行正确的比较并返回排序指示。
同样,由于qsort()
事先并不知道对象的大小,因此它将对象大小作为参数。就qsort()
而言,对象是在内存中连续排列的大小相等的字节。
最后,由于qsort()
执行的操作都不会导致错误,因此不会返回错误代码。实际上 是qsort()
可能失败的情况,这是传递给它的非法参数,但是在许多其他标准C库例程的传统中,它不保证对参数的任何错误检查在这种情况下承诺未定义的行为。