当使用“a> b”作为比较器时,qsort意外地工作

时间:2014-10-28 22:27:15

标签: c std qsort

我遇到了一个qsort比较器函数,它错误地使用“a> b”作为比较操作。我希望这个代码可以稍微随机地重新排序数组,但它正在我学校的教学服务器上工作(Ubuntu 12.04.4 LTS)。它没有按预期在我自己的笔记本电脑上工作,所以我不确定是什么原因导致这个bug。

#include <cstdio>
#include <cstdlib>

void print_arr(int* arr, size_t n) {
  for (int i = 0; i < n; i++)
    printf("%d ", arr[i]);
  printf("\n");
}

int int_compar(const void *x, const void *y)
{
  int i_x = *((int*)x);
  int i_y = *((int*)y);
  return i_x > i_y;
}

int main(int argc, char *argv[])
{
  int n = (1<<4);
  int in[n];

  for(int i = 0; i < n; i++)
    in[i] = rand() % 100;

  printf("Before: ");
  print_arr(in, n);

  qsort(in, n, sizeof(int), int_compar);

  printf("After: ");
  print_arr(in, n);

  return 0;
}

我的笔记本电脑:

$ ./qsort_test
Before: 7 49 73 58 30 72 44 78 23 9 40 65 92 42 87 3
After: 23 7 9 3 58 44 42 40 49 30 65 72 73 78 87 92

Ubuntu的:

$ ./qsort_test
Before: 83 86 77 15 93 35 86 92 49 21 62 27 90 59 63 26
After: 15 21 26 27 35 49 59 62 63 77 83 86 86 90 92 93

1 个答案:

答案 0 :(得分:1)

您违反了使用qsort的合同,从而调用了Undefined Behavior 具体来说,你的比较函数很糟糕:

  

7.22.5.2 qsort函数

     

概要

#include <stdlib.h>
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
     

描述
  2 qsort函数对一组nmemb个对象进行排序,其初始元素为   由base指出。每个对象的大小由size指定   3根据比较,数组的内容按升序排序   compar指向的函数,使用两个指向的参数调用   被比较的对象。 该函数应返回小于,等于或的整数   如果第一个参数被认为分别小于,等于,则大于零   或大于第二个。
  4如果两个元素相等,则它们在生成的排序数组中的顺序是未指定的   返回
  5 qsort函数不返回任何值。

它应该更符合:

int int_compar(const void *x, const void *y)
{
  int i_x = *(int*)x;
  int i_y = *(int*)y;
  return i_x > i_y - i_x < i_y;
}

现在,比较函数部分起作用而不是完全破坏,表示第一个是否大于第二个,但不区分它们是相等还是第二个更大 根据编写算法的方式,可能会使算法看起来完全相同,根本不对您的错误作出反应,或做一些有趣的事情。
例如,所有C ++标准库排序算法都只使用少于比较的值。