我正在尝试编写一个通用的快速排序:
void _qsort(void *ptr,
size_t lrange,
size_t rrange,
size_t size,
int (*cmp)(const void *, const void *))
{
if (lrange < rrange) {
size_t i, j;
void *key;
key = malloc(size);
i = lrange;
j = rrange;
memcpy(key, ptr + i * size, size);
while (i < j) {
while (i < j && (*cmp)(ptr + j * size, key) > 0)
j--;
if (i < j) {
memcpy(ptr + i * size, ptr + j * size, size);
i++;
}
while (i < j && (*cmp)(key, ptr + i * size) > 0)
i++;
if (i < j) {
memcpy(ptr + j * size, ptr + i * size, size);
j--;
}
}
memcpy(ptr + i * size, key, size);
_qsort(ptr, lrange, i - 1, size, cmp);
_qsort(ptr, i + 1, rrange, size, cmp);
}
}
我在int数组上写了一个简单的测试,这是cmp函数:
int cmp(const void *x, const void *y)
{
return *(int *)x - *(int *)y;
}
它导致核心转储,但是当我将lrange, rrange, i, j
的类型从size_t
更改为int
时,它运行正常,我无法理解,为什么?
答案 0 :(得分:3)
memcpy(key, ptr + i * size, size);
ptr
是void *
,您无法使用void *
指针算法,切换到标准库中的char *
(qsort
)。
答案 1 :(得分:2)
size_t i, j;
是无符号类型。如果无符号变量的值为0,并且减去1,则该值将环绕到该无符号类型的最大可能值。
这可能发生在一行:
j--;
和
_qsort(ptr, lrange, i - 1, size, cmp);
当该无效值用作数组的索引时,它将导致seg-fault,因为程序无法读取超出范围的地址。
请勿使用前缀为_
,_qsort
的名称,因为这些名称是为实现而保留的。