我不知道如何查找这个,甚至标题都令人困惑,甚至我对我在寻找的东西感到困惑,这个问题肯定已经被问过了,但它是如此具体地被发现,所以这里有一点背景:
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*)
和comparison是类型为:
的函数int(*)(const int*, const int*)
我想知道为什么编译器不高兴,因为它只需要强制转换地址。它甚至应该乐意给一个void*
指针一个类型。这真的很糟糕吗?比如未定义行为之类的?或者只是编译器在抱怨什么?
在已经给出了其他原因之后,还有一个。历史上有一些平台void *
和int *
有不同的位排列,我听说有一个平台void *
和int *
有不同的大小。函数指针强制转换并不总是有效。
const int *ia = (const int *)a;
const int *ib = (const int *)b;
可能不会编译成ia = a;
,而是编译成ia = a >> 1
;所以必须有一个地方来放置这些指令。
为什么他(编译器)不高兴
qsort()
期望的功能点类型为int (*)(const void *a, const void *b)
,而不是int (*)(const int *a, const int *b)
。编译器可以猜测其是否正确并执行强制类型转换,但是编译器对此类问题发出警告会更有效。
或者只是编译器在抱怨什么?
通过提醒你,你可以确定问题的严重程度。
除了@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)
习惯用法,并发出高效的代码。
qsort
函数的参数之一是您没有传递的类型的函数。所以你需要改变它
在比较器内部,可以将指针重铸为所需的类型。
另外,需要对传递给比较器函数的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;
}