我正在制作 C 动态数组库,有点。请注意,我只是在空闲时间做这件事,所以请不要推荐数百万个现有库。
我开始实现排序。该数组具有任意元素大小,定义为结构:
typedef struct {
//[PRIVATE] Pointer to array data
void *array;
//[READONLY] How many elements are in array
size_t length;
//[PRIVATE] How many elements can further fit in array (allocated memory)
size_t size;
//[PRIVATE] Bytes per element
size_t elm_size;
} Array;
我最初准备这个是从排序功能开始的:
/** sorts the array using provided comparator method
* if metod not provided, memcmp is used
* Comparator signature
* int my_comparator ( const void * ptr1, const void * ptr2, size_t type_size );
**/
void array_sort(Array* a, int(*comparator)(const void*, const void*, size_t)) {
if(comparator == NULL)
comparator = &memcmp;
// Sorting algorithm should follow
}
但是我了解到qsort
:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
显然,我可以将我的内部数组传递给 qsort
。我可以这样称呼:
qsort (a->array, a->length, a->elm_size, comparator_callback);
但是有一个问题 - qsort
的比较器签名读作:
int (*compar)(const void*,const void*)
memcmp
的签名是:
int memcmp ( const void * ptr1, const void * ptr2, size_t type_size );
qsort
的回调中缺少元素大小,这意味着当 NULL
作为回调传递时,我无法再拥有通用比较器函数。我可以手动生成最多 X 字节元素大小的比较器,但这听起来很难看。
我可以将 qsort
(或其他内置排序)与 memcpy
一起使用吗?还是我必须在内置比较器和内置排序功能之间做出选择?
最佳答案
C11 为您提供了一个(当然是可选的)qsort_s
function ,旨在处理这种特定情况。它允许您将用户提供的 void *
值(上下文指针)从调用代码传递到比较器函数。本例中的比较器回调具有以下签名
int (*compar)(const void *x, const void *y, void *context)
在最简单的情况下,您可以将指向大小值的指针作为上下文传递
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdlib.h>
...
int comparator_callback(const void *x, const void *y, void *context)
{
size_t elm_size = *(const size_t *) context;
return memcmp(x, y, elm_size);
}
...
qsort_s(a->array, a->length, a->elm_size, comparator_callback, &a->elm_size);
或者将指向整个数组对象的指针作为上下文传递可能有意义。
一些基于 *nix 的实现已经提供了类似的 qsort_r
function有一段时间,虽然它是非标准的。
关于我可以将 memcmp 与 qsort 一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40855385/