关于使用qsort对void*类型数组排序的技术咨询
咱们先拆解你的代码逻辑,再聊聊用qsort排序指针数组时要注意的几个关键问题:
现有实现的潜在风险
1. 指针转long的可移植性问题
不是所有平台上指针的宽度都和long一致——比如64位Windows系统中,long是32位,但指针是64位,这时候强制转换会直接截断高位地址,导致差值计算完全错误。
标准C提供了intptr_t/uintptr_t(定义在<stdint.h>中),这是专门用来安全存储指针整数表示的类型,应该优先使用它来做指针的数值转换。
2. 返回值溢出风险
你用(int)((long)(a) - (long)(b))作为返回值,当两个指针的地址差超过int的取值范围时,会触发整数溢出,导致返回值不符合qsort的要求(qsort要求比较函数返回负数/0/正数分别表示a小于/等于/大于b)。比如在64位平台上,两个指针差可能远大于int的最大值,这时候转成int就会出现错误的符号。
3. 指针比较的标准合规性
严格来说,C标准只允许指向同一数组对象的指针(或指向数组末尾的指针)进行大小比较,任意无关指针的比较属于未定义行为。虽然大多数现代平台会按内存地址的实际值来比较,但生产代码要注意这个限制。
修正后的实现方案
安全的比较函数
#include <stdint.h> int compare_ptrs(const void* a, const void* b) { const intptr_t addr_a = (intptr_t)a; const intptr_t addr_b = (intptr_t)b; if (addr_a > addr_b) { return 1; } else if (addr_a < addr_b) { return -1; } return 0; }
这个版本用intptr_t保证指针转换的安全性,通过分支判断返回明确的1/-1/0,彻底避免溢出问题。
正确调用qsort
调用时要确保参数正确:
// 排序你的指针数组 qsort(array, sizeof(array)/sizeof(array[0]), sizeof(void*), compare_ptrs);
这里sizeof(array)/sizeof(array[0])用来自动计算数组元素个数,比硬写2更灵活。
额外注意:内存泄漏
你的代码中用malloc分配了内存,但没有调用free释放,记得在程序结束前加上:
free(a); free(b);
测试验证逻辑
你构造数组时让array[0]的地址大于array[1],调用修正后的qsort后,数组会被从小到大排序,也就是array[0]变成地址更小的指针,array[1]是地址更大的指针,符合预期。
内容的提问来源于stack exchange,提问作者sanyassh

