You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于qsort比较函数使用减法实现的正确性疑问及测试

为什么qsort比较函数用减法实现会踩坑?

你这个观察太关键了!很多人图省事,在qsort的比较函数里直接用*(int*)a - *(int*)b返回结果,但这种写法暗藏严重的溢出风险,尤其是碰到INT_MIN(也就是-2147483648)的时候,直接就会出问题。

举个你提到的例子:当数组里有INT_MIN,比如int nums[]={-2147483648,1,2,3},当比较1和INT_MIN时,1 - INT_MIN的数学结果是2147483649,但int类型的最大值只有2147483647,这就触发了有符号整数溢出——这属于C语言里的未定义行为,程序可能返回错误的排序结果,甚至出现奇怪的崩溃。

我们可以用一段测试代码验证这个问题:

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>

int compare (const void * a, const void * b) {
    return ( *(int*)a - *(int*)b );
}

int main(void) {
    int nums[] = {INT_MIN, 1, 2, 3};
    int n = sizeof(nums)/sizeof(nums[0]);
    
    // 用有问题的比较函数排序
    qsort(nums, n, sizeof(int), compare);
    
    printf("排序结果:");
    for(int i=0; i<n; i++){
        printf("%d ", nums[i]);
    }
    printf("\n");
    
    // 单独看比较逻辑的问题
    int a_val = 1;
    int b_val = INT_MIN;
    printf("1 - INT_MIN 的计算结果:%d\n", a_val - b_val);
    return 0;
}

运行这段代码你会发现,1 - INT_MIN的输出不是预期的正数,而是一个负数(比如在大多数编译器上会输出-2147483647),这就导致qsort错误地认为1比INT_MIN小,最终排序结果完全错乱。

那正确的写法应该是什么样的?给你两种安全的方案:

方案一:用条件判断明确返回值

最直观的写法,完全避免溢出:

int compare(const void *a, const void *b) {
    const int x = *(const int*)a;
    const int y = *(const int*)b;
    if (x < y) return -1;
    if (x > y) return 1;
    return 0;
}

方案二:用简洁的布尔运算写法(C99及以上适用)

这个写法很巧妙,利用布尔值的隐式转换(true为1,false为0),同样不会有溢出问题:

int compare(const void *a, const void *b) {
    const int x = *(const int*)a;
    const int y = *(const int*)b;
    return (x > y) - (x < y);
}

总结一下:永远不要在qsort的比较函数里用减法返回结果,只要两个整数的差值超过int的范围,就会触发未定义行为。用条件判断或者上述的布尔运算写法,才是安全可靠的做法。

内容的提问来源于stack exchange,提问作者52coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:56:33