转换函数指针 [英] Casting function pointers

查看:101
本文介绍了转换函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个函数,该函数接收一个指向比较函数的指针和一个MyStructs数组,并应该根据比较函数对数组进行排序:

void myStructSort(
                  struct MyStruct *arr,
                  int size,
                  int (*comp)(const struct MyStruct *, const struct MyStruct *)) {
  qsort(arr, size, sizeof(struct MyStruct), comp);
}

不幸的是,这不能编译,因为qsort希望比较器接收void *自变量而不是const struct MyStruct *.我想到了几个不好的解决方案,并且想知道什么是正确的解决方案.

选项1

comp投射到int (*)(const void *, const void*).这会编译,但是是未定义的行为(请参见此SO问题). /p>

选项2

创建一个全局变量int (*global_comp)(const struct MyStruct *, const struct MyStruct *),并在myStructSort中设置global_comp=comp.然后创建一个函数:

int delegatingComp(const void *a, const void *b) {
  return globalComp((const struct MyStruct *)a, (const struct MyStruct *)b);
}

然后在myStructSort中调用qsort(arr, size, sizeof(struct MyStruct), delegatingComp).问题出在棘手的全局变量.

选项3

重新实现qsort.这在功能上是安全的,但是非常不好.

有一个神奇的完美第四选择吗?

修改

我无法更改myStructSort的API,并且正在使用gcc c99 -Wall -Wextra -Wvla编译代码.

解决方案

选项2破坏了线程安全性,因此我不会选择那个.

正如您指出的那样,选项3完全是错误的.没有理由重新实施quicksort并可能犯错.

选项1是UB,但可以在任何理智的编译器上使用.如果选择此选项,请确保添加评论.

我还会考虑:

选项4.重新设计myStructSort的界面以使用int (*)(const void *, const void*)或完全废弃它,然后直接调用qsort.基本上将其发送回Architecht,因为他的设计选择不当.

I am writing a function that receives a pointer to a comparison function and an array of MyStructs and is supposed to sort the array according to the comparison function:

void myStructSort(
                  struct MyStruct *arr,
                  int size,
                  int (*comp)(const struct MyStruct *, const struct MyStruct *)) {
  qsort(arr, size, sizeof(struct MyStruct), comp);
}

Unfortunately this doesn't compile because qsort expects the comparator to receive void * arguments and not const struct MyStruct *. I thought of several bad solutions and was wondering what the correct solution is.

Option 1

Cast comp to int (*)(const void *, const void*). This compiles but is undefined behavior (see this SO question).

Option 2

Create a global variable int (*global_comp)(const struct MyStruct *, const struct MyStruct *) and set global_comp=comp inside myStructSort. Then create a function:

int delegatingComp(const void *a, const void *b) {
  return globalComp((const struct MyStruct *)a, (const struct MyStruct *)b);
}

And in myStructSort call qsort(arr, size, sizeof(struct MyStruct), delegatingComp). The problem with this is the icky global variable.

Option 3

Reimplement qsort. This is functionally safe but very bad practice.

Is there a magical perfect fourth option?

Edit

I can't change the API of myStructSort and I am compiling my code using gcc c99 -Wall -Wextra -Wvla.

解决方案

Option 2 breaks thread-safety, so I wouldn't choose that one.

Option 3 is just plain wrong as you point out. There is no reason to re-implement quicksort and potentially make a mistake.

Option 1 is UB but it will work on any sane compiler. If you choose this option be sure to add a comment.

I would also consider:

Option 4. Redesign the interface of myStructSort to take int (*)(const void *, const void*) or scrap it entirely and call qsort directly. Basically send it back to the architecht, because he made a poor design choice.

这篇关于转换函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆