转换函数指针 [英] Casting function pointers
问题描述
我正在编写一个函数,该函数接收一个指向比较函数的指针和一个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屋!