如何复用qsort比较函数切换不同比较器?程序报错求助
问题原因与修复方案
为什么会出现这个警告?
1. 比较函数签名不兼容
qsort要求的比较函数必须是int (*)(const void*, const void*)类型——也就是参数必须是两个const void*。但你写的compare_harga和compare_pembayaran参数是struct propertySales*,和qsort要求的类型不匹配。
更致命的是,如果你在调用qsort时不小心写成了compare_harga()(加了括号),这就不是传递函数指针了,而是调用函数并把返回的int值当成指针传给qsort。在64位系统中,int是4字节,指针是8字节,两者大小不同,编译器直接抛出"int转指针大小不匹配"的警告,程序运行时也会因为传递了错误的地址而崩溃。
2. 类型转换的潜在风险
即使你没加括号,只是把struct propertySales*参数的函数指针强制转成compfn类型,编译器也会因为类型不兼容发出警告,而且这种转换可能导致运行时的未定义行为——因为qsort会传递const void*,而你的函数期望struct propertySales*,如果没有正确转换,会导致指针解析错误。
怎么修复?
第一步:修正比较函数的签名
把比较函数的参数改成const void*,内部再安全转换成const struct propertySales*:
int compare_harga(const void *elem1, const void *elem2) { const struct propertySales *a = (const struct propertySales*)elem1; const struct propertySales *b = (const struct propertySales*)elem2; if (a->hargaProperty < b->hargaProperty) return -1; if (a->hargaProperty > b->hargaProperty) return 1; return 0; } int compare_pembayaran(const void *elem1, const void *elem2) { const struct propertySales *a = (const struct propertySales*)elem1; const struct propertySales *b = (const struct propertySales*)elem2; if (a->totalPembayaran < b->totalPembayaran) return -1; if (a->totalPembayaran > b->totalPembayaran) return 1; return 0; }
第二步:正确传递函数指针给qsort
调用qsort时直接传函数名(函数的地址),不要加括号:
// 按单价排序 qsort(Arr, 100, sizeof(struct propertySales), compare_harga); // 切换成按总付款排序 qsort(Arr, 100, sizeof(struct propertySales), compare_pembayaran);
第三步:用typedef统一管理比较器(可选)
你定义的compfn类型是正确的,可以用它来切换比较器,让代码更清晰:
typedef int (*compfn)(const void*, const void*); compfn sort_func; // 切换到单价排序 sort_func = compare_harga; qsort(Arr, 100, sizeof(struct propertySales), sort_func); // 切换到总付款排序 sort_func = compare_pembayaran; qsort(Arr, 100, sizeof(struct propertySales), sort_func);
这样修改后,编译器警告会消失,程序也能正常切换比较器完成排序。
内容的提问来源于stack exchange,提问作者Raynaldy Dwi
相关产品推荐
相关产品推荐

