微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

解释 c 中 qsort() 函数中的类型转换?

如何解决解释 c 中 qsort() 函数中的类型转换?

1) 在这代码中,pLhspRhs 指向某个随机内存位置,那么这个随机内存位置的内容是如何被复制到 LHS 指向的位置的??

2) 解释 C 中 qsort() 中使用的比较器函数??

int comparator(const void *pLhs,const void *pRhs)
{

    int *lhs = (int *)pLhs;

    int *rhs = (int *)pRhs;
 

    return *lhs > *rhs;
}

这段代码构成了这个子集和程序

https://www-geeksforgeeks-org.cdn.ampproject.org/v/s/www.geeksforgeeks.org/subset-sum-backtracking-4/amp/?amp_js_v=a6&amp_gsa=1&usqp=mq331AQHKAFQArABIA%3D%3D#aoh=16210898076202&referrer=https%3A%2F%2Fwww.google.com&amp_tf=From%20%251%24s&ampshare=https%3A%2F%2Fwww.geeksforgeeks.org%2Fsubset-sum-backtracking-4%2F

解决方法

qsort 被写入以便它可以对任何类型的数据进行排序。大部分排序是在内存中移动项目,这可以通过移动表示数据的字节来完成:您不需要知道两个数组元素中字节的含义来交换它们,您只需要知道在哪里它们是以及每个中有多少字节。所以 qsort 可以接受一个 void * 部分到数组的开头和一个 size_t 告诉它每个元素中有多少字节,它不关心原始类型是什么void * 是。

但是,qsort 无法仅根据字节来确定排序顺序中的两个元素中的哪个更早。它可以完全按照字节中位的二进制值对所有数组元素进行排序,但有人可能希望以相反的顺序对数组进行排序或按字母顺序对字符串进行排序而忽略大小写或按浮点解释排序。这些中的每一个都是不同的排序,而不仅仅是按二进制值排序。所以 qsort 需要一个辅助程序。这是传递给它的比较例程。

由于 qsort 只被赋予一个 void *,它不知道数组元素的原始类型是什么,因此它无法将该类型传递给比较例程。比较例程必须将 void * 转换为正确的类型。每个比较例程都针对它比较的元素类型进行定制。它传递的指针不指向随机地址;它们指向正在排序的数组中的元素。

给定函数声明 int comparator(const void *pLhs,const void *pRhs),赋值 int *lhs = (int *) pLhs;void * 参数 pLhs 转换为 int * 变量 lhs。那么 *lhs 可以用作 intrhs 也可以。

您展示的示例代码中存在三个错误或缺陷。首先,比较例程被传递一个const void *。预计不会更改指向的值。所以它应该将指针转换为 const int *,而不是 int *

其次,C 中不需要强制转换。只需执行 const int *lhs = pLhs; 即可。编译器会在初始化 const void * 时自动将 const int * 转换为 lhs。 (在 C++ 中,这样的强制转换可能是必要的。)在 C 中,不鼓励这种强制转换,因为在某些情况下,它们可以通过逃避编译器在不存在强制转换时产生的警告消息来隐藏错误。事实上,这已经发生在这里。使用演员表,Apple Clang 11 不会发出初始化警告。如果没有强制转换,编译器会警告初始化会丢弃 const 限定符。

第三,return *lhs > *rhs; 不够用。 qsort 比较应该返回一个负值,如果左参数应该排在右之前,如果它们就排序顺序而言相同,则为零,如果左参数应该排在右之后,则返回正值正确的。所以升序的正确代码可能是:

return *lhs < *rhs ? -1 : *lhs == *rhs ? 0 : +1;

对于降序,可以是:

return *lhs > *rhs ? -1 : *lhs == *rhs ? 0 : +1;

如果您还不熟悉条件运算符,可以使用:

if (*lhs > *rhs)
    return -1;
else if (*lhs == *rhs)
    return  0;
else
    return +1;
,

这是一个 qsort 比较函数的例子。我将顶部对齐以显示类型的匹配。

int
cmp_float(void const *v1,void const *v2 )
{
        double const *d1 = v1,*d2 = v2;

    if (*d1 == *d2)
        return 0;
    else
        return *d1 > *d2 ? 1 : -1;
}

对于第三种情况,我首先使用了第二个“0”而不是“-1”......无论如何它都有效。


E.P. 的 A 说明了一切。除了可能:如果你想要一个slap-dash的演员,那么就这样做:

double d1 = *(double *)v1;

因此您可以在之后使用不带星号的 d1d2。在我上面的版本中,我需要第二次分配(如 double D1 = *d1)。隐式转换后的取消引用。

在正确的位置放一个 * 看起来不错。演员阵容一般都很丑陋。


随机内存位置

它不是随机的,它对应于被 qsorted 的两个数组元素。

将数组(指针、元素大小、n 个元素)和比较函数名称提供给 qsort() 的调用者必须知道他在排序什么:可以是字符数组或大型结构数组。或者(理想情况下)一个指针数组。

使用字符可能会有一些开销。为什么要传递两个长地址来比较两个字节?

对于更大的结构或(子)数组,改组的数量成为问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。