C 对多个类型使用qsort()

C 对多个类型使用qsort(),c,C,我想使用C的qsort()函数对每个具有不同类型的数组进行排序,如下所示: int a[] = {1, 2, 3}; const char *b[] = {"foo", "bar", "bas"}; my_defined_type_t *c[100]; for (i=0; i<100; i++) { fill(c[i]); } 不,您不能拥有泛型函数,因为类型现在在运行时在C中传递(与面向对象语言不同)。类型必须在编译时已知 因此,您需要有一个知道如何比较每个类型并告诉qsort的函数。

我想使用C的qsort()函数对每个具有不同类型的数组进行排序,如下所示:

int a[] = {1, 2, 3};
const char *b[] = {"foo", "bar", "bas"};
my_defined_type_t *c[100]; for (i=0; i<100; i++) { fill(c[i]); }

不,您不能拥有泛型函数,因为类型现在在运行时在C中传递(与面向对象语言不同)。类型必须在编译时已知


因此,您需要有一个知道如何比较每个类型并告诉
qsort
的函数。

不,您不能有一个泛型函数,因为类型现在在运行时在C中传递(与面向对象语言不同)。类型必须在编译时已知


因此,您需要有一个函数,它知道如何比较每种类型,并告诉
qsort

我想如果您神奇地知道这些类型,您可以做到,但为什么要麻烦呢?另外,你也有要通过的尺寸,所以你需要在两个地方进行检查


不知道这有什么好处。

我想你可以,如果你能神奇地知道类型,但为什么要麻烦呢?另外,你也有要通过的尺寸,所以你需要在两个地方进行检查

不确定这有什么好处。

C没有,因此无法知道a
void*
所指的是什么类型

每个类型需要一个比较函数,并且必须使用正确的回调调用
qsort

C没有,因此无法知道a
void*
指向的是什么类型

每个类型需要一个比较函数,并且必须使用正确的回调调用
qsort

您的

int myGrandUnifiedComparisonFunction(const void* a, const void* b) {

    if *a, *b are integers: intComparatorCode;
    if *a, *b are strings: stringComparitorCode;
    if *a, *b are my_defined_type_t's: myDefinedTypeComparitorCode;
   /* etc. */
}
非常好。你试过实现它吗

问题是,没有办法用C或C++实现它。。无法确定void*指向哪种类型的变量。

您的想法

int myGrandUnifiedComparisonFunction(const void* a, const void* b) {

    if *a, *b are integers: intComparatorCode;
    if *a, *b are strings: stringComparitorCode;
    if *a, *b are my_defined_type_t's: myDefinedTypeComparitorCode;
   /* etc. */
}
非常好。你试过实现它吗


问题是,没有办法用C或C++实现它。。无法确定void*指向哪种类型的变量。

有两个问题需要考虑:

1)信息问题

您的比较函数得到两个空指针。这只是一些位模式,可能意味着什么。例如,C不向浮点数或字符指针附加任何信息,因此如果事先不知道某个数据段是一个还是另一个,则无法判断该数据段

这就是说,您可以通过将数据包装到结构中,并使用一个枚举值来告诉您其中的内容,从而自行附加此信息。但从技术上讲,您不会比较浮点或字符指针,而是比较包装的浮点和包装的字符指针。比如:

enum { Float, String, MyType } typ;

typedef struct { 
    typ t;
    union {
       float f;
       char *s;
       myType mt;
    } wrappedData;
然后,您只需编写一个函数来比较
wrappedata*
。 这正是每种动态语言所做的

然后,即使是您的大统一函数也必须对它们进行适当的比较,也就是说,每种类型的比较都有所不同,所以您不会获得太多。相反,你会把逻辑组合成一个函数,而这个函数实际上并不属于同一个函数

效率问题

虽然这可能不会困扰您,但展开指针并检查其类型将在每个比较操作中完成,这可能会大大增加排序的运行时间

结论:


您必须采取某种方式来包装您的数据,这是一个值得怀疑的优势,也是一个显著的劣势(效率)。不要这样做。

有两个问题需要考虑:

1)信息问题

您的比较函数得到两个空指针。这只是一些位模式,可能意味着什么。例如,C不向浮点数或字符指针附加任何信息,因此如果事先不知道某个数据段是一个还是另一个,则无法判断该数据段

这就是说,您可以通过将数据包装到结构中,并使用一个枚举值来告诉您其中的内容,从而自行附加此信息。但从技术上讲,您不会比较浮点或字符指针,而是比较包装的浮点和包装的字符指针。比如:

enum { Float, String, MyType } typ;

typedef struct { 
    typ t;
    union {
       float f;
       char *s;
       myType mt;
    } wrappedData;
然后,您只需编写一个函数来比较
wrappedata*
。 这正是每种动态语言所做的

然后,即使是您的大统一函数也必须对它们进行适当的比较,也就是说,每种类型的比较都有所不同,所以您不会获得太多。相反,你会把逻辑组合成一个函数,而这个函数实际上并不属于同一个函数

效率问题

虽然这可能不会困扰您,但展开指针并检查其类型将在每个比较操作中完成,这可能会大大增加排序的运行时间

结论:


您必须采取某种方式来包装您的数据,这是一个值得怀疑的优势,也是一个显著的劣势(效率)。不要这样做。

*a,*b
错误,对于
void*
错误,我们有void指针,而不是void value,您的GUCF如何知道a和b是整数、字符串还是其他任何东西?只是。。不。。尽可能多地使用typesafety。它是来帮助你的you@Vicky不知何故,我希望C能够做到这一点:某种类型的动态类型检查?@user1505713否。看起来您想编写
python
code
*a、*b
错误,错误为
void*
,我们有void指针而不是void值,您的GUCF如何知道a和b是int、string还是其他任何东西?只是。。不。。尽可能多地使用typesafety。它是来帮助你的you@Vicky不知何故,我希望C能做到这一点:某种类型的动态类型检查?@user1505713否。看起来你想写
python
codeyes事实上,没有强制转换的取消引用void指针是编译时错误——语义错误的一个例子是事实上没有强制转换的取消引用void指针是编译时错误-