我不知道如何查找,甚至标题也令人困惑,甚至我对我要查找的内容也感到困惑,而且这个问题肯定已经有人问过了,但它太具体了,所以这里有一些背景:
int comparison(const int* a, const int* b) {
return *a - *b;
}
int main(int argc, char const *argv[])
{
int arr[3] = {1,6,-2};
qsort(arr,3,sizeof(int),comparison);
return 0;
}
嗯,它确实有效,但是编译器给了我一个警告,因为 qsort 需要一个类型的函数:
int(*)(const void*, const void*)
并且比较是一个函数类型:
int(*)(const int*, const int*)
我想知道为什么编译器不高兴,因为它只需要强制转换地址。甚至应该很高兴为 void*
指针指定类型。这真的很糟糕吗?像未定义的行为之类的?或者只是编译器抱怨什么?
答案 0 :(得分:2)
在给出其他原因之后,还有另一个原因。历史上有 void *
和 int *
具有不同位安排的平台,我听说过 void *
和 int *
的大小不同的传闻。该函数指针转换并不总是有效。
const int *ia = (const int *)a;
const int *ib = (const int *)b;
可能不会编译为 ia = a;
而是编译为 ia = a >> 1
之类的东西;所以真的必须有一个地方来放置这些说明。
答案 1 :(得分:1)
qsort
函数将您未传递的类型的函数作为其参数之一。所以你需要改变它。
在比较器中,您可以将指针重新转换为所需的类型。
此外,您需要 dereference 传递给比较器函数的 const int
指针的值:
#include <stdio.h>
#include <stdlib.h>
static int
comparator(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;
}
static void
printArr(int arr[], int n)
{
int i;
for (i = 0; i < n; ++i) {
printf("%d ", arr[i]);
}
}
int
main(int argc, const char **argv)
{
int arr[3] = {1, 6, -2};
qsort(arr, 3, sizeof(int), comparator);
printArr(arr, 3);
return EXIT_SUCCESS;
}
答案 2 :(得分:1)
为什么他(编译器)不高兴。
qsort()
需要一个 int (*)(const void *a, const void *b)
类型的函数点,而不是 int (*)(const int *a, const int *b)
。编译器可以猜测其OK并进行强制转换,但编译器警告此类问题的效率更高。
或者只是编译器抱怨什么?
通过温暖你,你可以确定问题的程度。
除了 @Alex Reynolds 好的答案,注意 *a - *b
可能会溢出,导致比较错误。
相反:
int comparison(const void *a, const void *b) {
const int *ia = (const int *)a;
const int *ib = (const int *)b;
return (*ia > *ab) - (*ia < *ib);
}
优秀的编译器会识别 (p>q) - (p<q)
习语并发出高效的代码。