带有void*参数强制转换的函数指针



我不知道如何查找这个,甚至标题都令人困惑,甚至我对我在寻找的东西感到困惑,这个问题肯定已经被问过了,但它是如此具体地被发现,所以这里有一点背景:

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;
}

最新更新