qsort排序无符号长整型数组时被填充为全零的问题排查
解决qsort排序unsigned long数组时被填充为零的问题
看起来你在使用qsort排序unsigned long数组时踩了两个关键的坑,这直接导致了数组被意外覆盖为零。咱们一步步拆解问题和修复方案:
1. qsort参数传递的致命错误
首先得明确qsort的参数要求,它的函数签名是:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
这里的第二个参数nmemb是数组的元素个数,而不是数组的总字节数!但你的调用里:
qsort(scores[c], sizeof(scores[c]), sizeof(scores[c][0]), comparator);
把sizeof(scores[c])(整个数组行的总字节数)传给了nmemb,这会让qsort误以为数组有这么多个元素——比如如果scores[c]有5个unsigned long元素,sizeof(scores[c])就是5*8=40(假设long是8字节),qsort会试图处理40个元素,远远超出数组实际长度,直接造成内存越界访问,最终把你的数组覆盖成零(或者其他随机垃圾值)。
修正后的调用方式
你需要把第二个参数改成实际的元素个数:
- 如果是固定长度的二维数组,比如
unsigned long scores[10][20],那第c行的元素个数就是20:qsort(scores[c], 20, sizeof(scores[c][0]), comparator); - 如果想动态计算元素个数(更通用),可以用总字节数除以单个元素的字节数:
size_t elem_num = sizeof(scores[c]) / sizeof(scores[c][0]); qsort(scores[c], elem_num, sizeof(scores[c][0]), comparator);
2. 比较器的unsigned类型适配问题
从你给出的比较器片段来看,需要注意unsigned long的比较逻辑不能直接用减法返回结果。比如如果写return *(unsigned long*)p - *(unsigned long*)q,当左边的值小于右边时,因为是无符号类型,差值会溢出成一个很大的正数,qsort会错误地认为左边的值更大,导致排序逻辑完全混乱。
正确的比较器实现应该是:
int comparator(const void *p, const void *q) { const unsigned long val_a = *(const unsigned long *)p; const unsigned long val_b = *(const unsigned long *)q; if (val_a < val_b) { return -1; // 表示val_a应该排在val_b前面 } else if (val_a > val_b) { return 1; // 表示val_a应该排在val_b后面 } return 0; // 两个值相等 }
3. GDB调试的验证点
你可以在GDB里做这些操作来确认修复效果:
- 调用
qsort之前,用print scores[c]打印数组初始值,确认数据是正确的 - 计算并打印
elem_num的值,检查是否等于数组实际的元素个数 - 单步跟踪
qsort的执行,观察内存访问是否在合法范围内
内容的提问来源于stack exchange,提问作者GenTel
相关产品推荐
相关产品推荐

