【问题标题】:How do C functions like qsort work with different datatypes?像 qsort 这样的 C 函数如何处理不同的数据类型?
【发布时间】:2012-11-09 10:57:50
【问题描述】:

stdlib.h中,有一个带有原型的函数qsort()的声明:

void qsort( void *ptr, size_t count, size_t size,
        int (*comp)(const void *, const void *) );

显然这是一个泛型编程。 我想知道它是如何实现的,如何从 void * 类型中获取元素?

【问题讨论】:

  • 大多数答案的注意事项:这个问题不是关于如何使用 qsort(),而是关于如何使用 qsort()。 qsort 在内部可以计算出元素在 void* 中的位置

标签: c generics void-pointers


【解决方案1】:

void * 指针根据size_t sizeqsort 中的第三个参数)进行强制转换

首先我们将void* 类型转换为char*,然后根据size 进行指针运算(因为char 需要1 字节,所以添加大小将得到正确的指针运算)

编辑:(用于内置数据类型)

char *ptr = (char*)vp; //here vp is void *p

*(ptr + (n-1)*size); //will give you nth element 

例如

size =1 and want 3rd element it means it will give you 3rd char
size =4 and want 3rd element it means it will give you 3rd int or float
size =2 and want 3rd element it means it will give you 3rd short int
size =8 and want 3rd element it means it will give you 3rd double

注意:大小是实现定义的,因此它可能因编译器而异

【讨论】:

  • 是的,我想知道的是具体流程。比如如何获取ptr中的第3个元素?
【解决方案2】:
#include <stdio.h>

void compare_first_to_rest(void *ptr, size_t nelem, 
   size_t size, int (*cmp)(const void*, const void*)) {
    unsigned i;
    for(i = 1; i < nelem; ++i)
        {
        int res = cmp(ptr, (char*)ptr + i * size);
        if(res < 0)
            printf("First element is less than element at %u\n", i);
        else if(res > 0)
            printf("First element is greater than element at %u\n", i);
        else
            printf("First element is equal to element at %u\n", i);
        }
}

int icmp(const void *x, const void *y) {
   return *(int*)x - *(int*)y;
}

int main()
{
   int x[] = { 5, 3, 6, 2, 4, 8, -1, 10 };
   compare_first_to_rest(x, 8, sizeof(int), icmp);
}

如您所见,`compare_first_to_rest' 不知道它在第一个参数中接收到的元素的类型。但是知道了每一个的大小,它就可以得到一个指向每一个的指针,然后让函数指针来完成这项工作。

【讨论】:

    【解决方案3】:

    最后一个参数是一个函数指针。正如您隐含地提到的,您必须在某处实现了此功能。 但是当你实现它时,你确实知道指针之王实际上是你的 void* 元素。

    在您的 comp 函数中,您必须将 2 个参数转换为您要使用的指针类型,如下所示:

    int myCompFn(const void * e1, const void * e2)
    {
        MyType *elem1=(MyType*)e1;
        MyType *elem2=(MyType*)e2;
        ... /* then compare elem1 and elem2 regarding to there definition */
    }
    

    【讨论】:

      猜你喜欢
      • 2019-05-04
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 2021-05-26
      • 2017-06-04
      相关资源
      最近更新 更多