qsort功能比较困惑我

52c*_*der 7 c qsort

我看到很多人在qsort比较器函数中使用减法.我认为这是错误的,因为在处理这些数字时:int nums[]={-2147483648,1,2,3}; INT_MIN = -2147483648;

int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}
Run Code Online (Sandbox Code Playgroud)

我写了这个函数来测试:

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

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

int main(void)
{
    int a = 1;
    int b = INT_MIN;
    printf("%d %d\n", a,b);
    printf("%d\n",compare((void *)&a,(void *)&b));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

1 -2147483648
-2147483647
Run Code Online (Sandbox Code Playgroud)

a > b所以输出应该是积极的.我看过很多书写得像这样.我认为这是错的; 处理int类型时应该这样写:

int compare (const void * a, const void * b)
{
    if(*(int *)a < *(int *)b)
        return -1;
    else if(*(int *)a > *(int *)b)
        return 1;
    else 
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么许多书籍和网站以这种误导的方式写作.如果您有任何不同的观点,请告诉我.

chu*_*ica 7

我认为这是错误的

是的,简单的减法可能导致int溢出,这是未定义的行为,应该避免.

return *(int*)a - *(int*)b;  // Potential undefined behavior.
Run Code Online (Sandbox Code Playgroud)

一个常见的习语是减去两个整数比较.各种编译器都认识到这一点并创建了高效良好的代码. 保留const-ness也很好的形式.

const int *ca = a;
const int *cb = b;
return (*ca > *cb) - (*ca < *cb);
Run Code Online (Sandbox Code Playgroud)

为什么许多书籍和网站都以这种误导的方式写作.

return *a - *b;在概念上很容易消化 - 即使它提供了极端值的错误答案 - 通常学习者代码省略了边缘条件来理解 - "知道"价值永远不会很大.

或者考虑 与NaN 相比long doubles的复杂性.

  • 为了避免潜在的编译器警告(应该启用它来检测其他问题),你应该保留指针参数的常量:`return(*(const int*)a>*(const int*)b) - (*(const int*)a <*(const int*)b);` (2认同)