简体   繁体   English

带有 void* 参数转换的 function 指针

[英]function pointers with void* argument casting

I have no idea on how to look this up, even the title is confusing, even I am confused about what I'm looking for, and the question has for sure already been asked but it's so specific to be found, so here a bit of context:我不知道如何查找这个,即使标题令人困惑,即使我对我正在寻找的内容感到困惑,而且这个问题肯定已经被问过了,但它是如此具体,所以这里有点上下文:

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

Well, it does work, but the compiler gives me a warning, because qsort wants a function of type:好吧,它确实有效,但编译器给了我一个警告,因为 qsort 想要一个 function 类型:

int(*)(const void*, const void*) 

and comparison is a function of type:比较的是 function 类型:

int(*)(const int*, const int*) 

I want to know why the compiler is not happy because it just has to cast the address.我想知道为什么编译器不高兴,因为它只需要转换地址。 It should even be happy to give a type to a void* pointer.甚至应该很高兴为void*指针提供类型。 Is this really bad?这真的很糟糕吗? Like an undefined behavior or something?像未定义的行为或什么? Or just the compiler whining about nothing much?或者只是编译器抱怨什么?

After other reasons already given, there's another one.在已经给出了其他原因之后,还有另一个原因。 Historically there were platforms for which void * and int * had different bit arrangements, I've heard rumor of one where void * and int * were different sizes.从历史上看,有些平台的void *int *有不同的位排列,我听说过一个void *int *大小不同的平台。 That function pointer cast won't always work. function 指针转换并不总是有效。

  const int *ia = (const int *)a;
  const int *ib = (const int *)b;

might not compile away to ia = a;可能无法编译为ia = a; but rather to something like ia = a >> 1 ;而是类似于ia = a >> 1 ; So there's really got to be a place for those instructions to be.所以真的必须有一个地方来放置这些指令。

The qsort function takes as one of its arguments a function of a type you are not passing. qsort function 将 arguments 一个 function 作为您未通过的类型之一。 So you'll need to change that.所以你需要改变它。

Inside the comparator, you can recast the pointers to the desired type.在比较器内部,您可以将指针重新转换为所需类型。

Additionally, you need to dereference the values of the const int pointers you are passing into the comparator function:此外,您需要取消引用传递给比较器 function 的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;
}

why he (the compiler) is not happy.为什么他(编译器)不高兴。

qsort() expects a function point of type int (*)(const void *a, const void *b) , not int (*)(const int *a, const int *b) . qsort()需要一个int (*)(const void *a, const void *b)类型的 function 点,而不是int (*)(const int *a, const int *b) The compiler could guess its OK and beform a cast, yet it is more productive for the compiler to warn about such problems.编译器可以猜测它的 OK 并进行强制转换,但编译器对此类问题发出警告会更有效率。

Or just the compiler whining about nothing much?或者只是编译器抱怨什么?

By warming you, you are allowed to determine the degree of the problem.通过加热你,你可以确定问题的程度。


In addition to @Alex Reynolds good answer, note that *a - *b may overflow, resulting in the wrong comparison.除了@Alex Reynolds好的答案,请注意*a - *b可能会溢出,导致比较错误。

Instead:反而:

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

Good compilers recognize the (p>q) - (p<q) idiom and emit efficient code.好的编译器会识别(p>q) - (p<q)习语并发出高效的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM