0

我是 C 语言的初学者,想习惯术语和指针。在寻找对数值数组的元素进行排序的方法时,我发现了以下工作函数原型。该函数是 qsort,它使用指针。现在我的理解是“const”这个词确保值 a 和 b 不变,但指针不变。如果我在这里错了,请纠正我。我的问题是:

  1. 为什么我们一开始void *就不能用的功能int *呢?
  2. 返回部分的构造如何*(int*)a工作?
  3. 为什么 qsort 算法需要这么多参数?

    int compare (const void *a, const void *b)
    {
         return ( *(int*)a - *(int*)b ); 
    }
    

非常感谢您的回答。PS:这对我来说是一项相当复杂的任务。

4

4 回答 4

2
  1. qsort以这种方式制作,因此它可以用作通用分拣机。如果它int从一开始就使用它只能用于比较整数。例如,您还可以通过这种方式将字符串strcmp作为比较函数传递给qsort.
  2. *(int*)a转换a为指向-的指针int,然后取消引用它,因此您获得了存储在的整数a。请注意,这不会改变aa指向的值。
  3. qsort需要 4 个参数:要排序的数组、该数组中的元素数量和元素的大小,最后是比较函数。它需要所有这些信息,因为它再次被尽可能地通用。

    它需要元素的数量,因为在 C 中指针不携带有关其后缓冲区大小的信息。它需要知道每个元素的大小,以便正确地将元素传递给比较函数。例如,要比较ints,您将sizeof(int)作为 size 参数传递。要比较字符串,您将使用sizeof(char *).

H2CO3 建议的ADDIT使用的原因const void *是表明比较功能可能不会改变 和 所指向的ab。当然,这是为了确保对数组进行排序不会突然改变数组中的值。而且,正如 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
于 2013-10-29T22:31:19.353 回答
2

现在我的理解是“const”这个词确保值ab不变但不是指针

你理解错了。

 const int *a;  

声明a为指向常量int类型的指针。这意味着该词const确保您无法a通过修改来修改变量指向的值*a

为什么我们使用void *这个函数我们不能从一开始就使用int *?

void *用于指向任何类型的变量。

返回部分的构造如何*(int*)a工作?

*(int *)用于转换a为指向int然后取消引用它以获取存储在它指向的位置的值。

于 2013-10-29T22:43:14.363 回答
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;
}
于 2013-10-29T22:35:40.290 回答
0

qsort()函数是作为通用例程实现的通用算法的示例。这个想法是让它对排序任意对象有用,而不仅仅是intor float。因此(并且由于 C 语言设计),qsort()采用比较函数作为接受两个通用(在 C 意义上)指针的参数。由该函数(由qsort()用户提供)将这些指针转换为正确的类型,执行正确的比较并返回排序指示。

同样,由于qsort()事先不知道对象有多大,所以它以对象大小作为参数。就qsort()目前而言,对象是在内存中连续排列的大小相等的字节块。

最后,由于qsort()执行的任何操作都不会导致错误,因此它不会返回错误代码。实际上存在可能失败的情况qsort(),即传递给它的非法参数,但在许多其他标准 C 库例程的传统中,它不保证在这种情况下对承诺未定义行为的参数进行任何错误检查。

于 2013-10-29T22:31:55.490 回答