【问题标题】:without passing arguments how compare funcation work不传递参数比较函数如何工作
【发布时间】:2023-03-21 02:37:01
【问题描述】:

我想对 struct 数组进行排序,但是在理解比较函数的逻辑时,我感到困惑的是,当它在不传递参数的情况下调用 qsort() 函数时,比较函数是如何工作的

在 Windows 上的代码块上使用 GCC:

代码

int compare(const void * a, const void * b);

struct cricketers
{
  int avrun;
  char name[30];
  int age;
  int notm;
}india[Max] = {
  122, "Sachin Tendulkar", 30, 67,
  97, "Virendra Sehwag", 35, 56,
  66, "Irfan Pathan", 32, 45,
  153, "Yusuf Pathan", 36, 21,
  101, "Yuvaraj Singh", 32, 45,
};

int main()
{
  int i;
  qsort(india, 5, sizeof(struct cricketers), compare);

  for (i = 0; i < 5; i++)
  {
    printf("Name : %s", india[i].name);
    printf("\nAge : %d", india[i].age);
    printf("\nTotal Test Matches played : %d", india[i].notm);
    printf("\nAverage Run : %d\n\n\n", india[i].avrun);
  }
  _getch();
  return 0;
}

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

【问题讨论】:

  • qsort 函数在内部调用compare 并将正确的参数传递给它。但是,您实现 compare 的方式,如果您以这种方式使用它,您会得到未定义的行为。
  • compare 函数传递了两个指针,它们必须转换为指向 struct cricketers 的指针。然后,您可以比较结构的成员。通常,您应该比较数据,而不是减去它,以防止溢出。看起来您试图通过利用您要比较的成员是struct 中的第一个成员来走捷径。这是一种糟糕的做法。
  • @Blaze 请解释更多
  • 如果我写变量=比较;这是什么意思
  • 这是一个回调函数。它被qsort而不是你调用。

标签: c sorting comparison quicksort qsort


【解决方案1】:

函数qsort在内部调用比较函数,传递给它的指向数组的两个元素的空指针。

根据 C 标准(6.7.2.1 结构和联合说明符),结构的第一个成员的地址等于结构类型的整个对象的地址。

15 在结构对象中,非位域成员和单元 位域所在的地址按顺序增加 在其中声明它们。 指向结构对象的指针, 适当转换,指向其初始成员(或者如果该成员是 一个位域,然后到它所在的单元),反之亦然。 结构对象内可能有未命名的填充,但在其 开始

因此,例如参数a 转换为int * 类型的值会产生结构的数据成员int avrun 的地址。

尽管如此,这个表达式(*(int*)a - *(int*)b) 可能会由于有符号整数的溢出而调用未定义的行为。

我会这样写比较函数。

int compare( const void *a, const void *b )
{
    const struct cricketers *left  = ( const struct cricketers * )a;
    const struct cricketers *right = ( const struct cricketers * )b;

    return ( right->avrun < left->avrun ) - ( left->avrun < right->avrun ); 
}

【讨论】:

  • 请解释overfloating mean and return ( right->avrun avrun ) - ( left->avrun avrun );像 return ( if ( right->avrun avrun) ) - ( if ( left->avrun avrun )); 一样工作
  • @hirico 表达式的结果可能例如太大而无法存储在 int 类型的对象中。
  • 返回(右->avrunavrun)-(左->avrunavrun);像 return ( if ( right->avrun avrun) ) - ( if ( left->avrun avrun )); 一样工作
  • @hirico 您不得在表达式中使用语句。表达式 ( right->avrun avrun ) 返回 1 或 0。因此,如果表达式返回 1,则第二个表达式 (left->avrun avrun ) 返回 0,结果等于 1 (1 - 0)
猜你喜欢
  • 2016-02-13
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
  • 2011-05-22
  • 2020-11-25
相关资源
最近更新 更多