C语言使用qsort对整数数组升序排序未生效的问题排查
问题根因定位
你的代码存在两处违反qsort使用规则的核心错误,完全对应了你遇到的“comp函数被正常调用,但原数组始终没有被修改、排序无效果”的现象:
错误1:比较函数的返回值逻辑完全错误
你在comp函数中写的逻辑:
int *s1 = (int *)a; int *s2 = (int *)b; return (s1 - s2);
这里s1、s2是指向数组元素的int*类型指针,直接做指针减法得到的是两个指针在内存中的偏移量,和两个指针指向的整数值没有任何对应关系。
举个直观例子:数组中相邻存放的5(下标2)和3(下标3),对应的指针做差会得到-1,但两个元素的真实数值差是5-3=2。这种情况下比较函数的返回值完全不符合qsort对比较结果的要求,根本无法正确反映元素的大小关系。哪怕修正了size参数的错误,这种写法也会让qsort误以为内存中位置靠前的元素数值更小,完全达不到按实际值排序的效果。
正确写法应该先解引用指针拿到指向的整数值,再返回两者的差值:
return *s1 - *s2;
错误2:qsort的元素大小参数传值错误
qsort的标准函数原型为:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
其中第三个参数size需要传入单个待排序元素的字节长度,但你代码中传入的是sizeof(a)——这是整个数组的总字节数(对包含4个int的数组来说就是16字节),远大于单个int元素实际占用的4字节。
参数错传后,qsort会按照“每个元素占16字节”的规则遍历寻址,而你的整个数组总长度才16字节,这就导致qsort实际操作的全是数组边界外的非法内存,哪怕comp函数被正常触发,也根本碰不到你定义的数组元素,自然不会让原数组产生任何修改。
正确写法应该将元素大小参数改为单个元素的字节长度,比如sizeof(a[0]):
qsort(a, 4, sizeof(a[0]), comp);
修正后的可正常运行代码
#include <stdio.h> #include <stdlib.h> int comp (const void *a, const void *b) { int s1 = *(int *)a; int s2 = *(int *)b; return s1 - s2; } int main() { int a[] = { 1, 2, 5, 3 }; qsort(a, 4, sizeof(a[0]), comp); for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { printf("%d ", a[i]); } return 0; }
内容的提问来源于stack exchange,提问作者Mateaș Mario
相关产品推荐
相关产品推荐

