【问题标题】:Why comparator in qsort has to be in this way?为什么 qsort 中的比较器必须以这种方式?
【发布时间】:2012-12-20 12:42:37
【问题描述】:

根据 C 参考,标准库中提供的 qsort 函数具有以下形式

void 
qsort ( void * base, size_t num, size_t size, int ( * compar ) ( const void *, const void * ) );

我的问题是为什么比较函数必须有 const void * 形式的参数,const void * 是什么意思

另一个问题是如果一个函数接受const void *形式的参数,它可以改变这个指针指向的值吗?

例子:

static int double_a_number(const void * val){
    *(int *)val = *(int *)val * 2;
    return 0;
}

这真的会使变量 val 翻倍吗?

感谢您的帮助!

【问题讨论】:

  • 第二个问题,不能直接输入就知道吗?
  • 对于第二个问题:是的,提供了使用int 对象的地址调用它。
  • @Pointy 好吧,由于未定义的行为,它在大多数情况下都可以工作。在某些情况下,最好知道它是否总是有效,而不仅仅是“在这种情况下”。
  • @Pointy 通过实验进行编程(“找出”)总是一个坏主意。特别是对于 C,其中许多属性是实现定义的、未指定的或未定义的。看,当我将空指针传递给 printf 时,它会打印“(null)”!这是对下一次实施的惊喜的保证。
  • 这个问题是两个问题。由于这两个问题不一定相互依赖,因此您最好发布两个问题。

标签: c void-pointers qsort


【解决方案1】:

为什么比较函数必须有const void *形式的参数

因为这是 C 中最通用的类​​型。请记住,qsort 可用于对 any 类型的数组进行排序。

另一个问题是如果一个函数接受const void *形式的参数,它可以改变这个指针指向的值吗?

必须抛弃const。这通常是一个坏主意(这肯定会出乎意料,而且还可能导致未定义的行为或崩溃)。而且它在比较器函数中肯定没有意义!

【讨论】:

  • 比较器不应该改变被比较的对象,这不是一个温和的提醒吗?
  • 但实际上我尝试了第二个,奇怪的是它真的改变了 val 指向的值。为什么会这样?
  • @dorafmon:如果底层对象不是真正的const,则丢弃const 并修改底层对象是有效的。但同样,这是出乎意料的(即让您的函数的用户感到惊讶)!
  • @OliCharlesworth 谢谢,我想我明白了。
  • 如果某些东西作为const 传递给一个函数,编译器完全有可能依赖于你不撒谎,因此在函数调用后不会重新加载该值 -> qsort 函数本身的意外影响。为什么任何理智的人会编写一个改变值的比较函数,这超出了我的理解......
猜你喜欢
  • 2020-07-28
  • 1970-01-01
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
  • 2021-06-10
  • 2011-04-19
  • 1970-01-01
相关资源
最近更新 更多