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

bsearch 的不同比较函数

如何解决bsearch 的不同比较函数

cmp func 似乎都有效;无法理解在 qsort_cmp 的情况下如何解析 int* 类型的 arg1。 据我所知:int* 被传递给 qsort_cmp,在那里它被更改为 void*,然后在 return 语句中转换为 struct s*。到目前为止没问题,但是转换对象应该有一个名为 b 的成员,它的转换类型有但它的实例没有...

struct s { int a,b; };

int qsort_cmp(const void *r1,const void *r2) {
     return ((struct s*) r1)->b - ((struct s*) r2)->b;
}

int bsearch_cmp(const void *key,const void *r2) {
     return *(int*) key - ((struct s*) r2)->b;
}

/* themap is already qsorted */
int k = 'w'//hatever;
void *ret = bsearch(&k,themap,thenumber_ofelements,sizeof(one_element),qsort_cmp);

解决方法

这些比较函数不可互换:一个比较两个参数的 b 字段,另一个比较第一个参数直接指向的 int 和结构的 b 字段第二个论点所指出的。如果使用 a 字段而不是 b,它们将是等效的,因为 a 字段位于结构的开头。

这里是规范:

7.22.5.1 搜索功能

[...]

compar 所指向的比较函数被调用,其中有两个参数依次指向键对象和数组元素。如果键对象分别被认为小于、匹配或大于数组元素,则该函数应返回一个小于、等于或大于零的整数。

因此第一个参数可以是指向 int 的指针,第二个参数可以是指向结构数组的指针,只要比较函数与 bsearch 调用方案一致

相反,qsort 中使用的比较函数是通过 2 个指向数组元素的指针调用的,因此两者都是指向 s 结构的指针。

但是请注意,减去 2 个 int 值并不是产生比较结果的可靠方法,因为此减法可能会导致许多值溢出:例如 INT_MIN - 1。更好的方法是这样的:

struct s { int a,b; };

int qsort_cmp(const void *r1,const void *r2) {
    const struct s *s1 = r1;
    const struct s *s2 = r2;
    return (s2->b < s1->b) - (s1->b < s2->b);
}

int bsearch_cmp(const void *key,const void *r2) {
    const int *ip = key;
    const struct s *s2 = r2;
    return (s2->b < *ip) - (*ip < s2->b);
}

现代编译器为此生成无分支代码:https://godbolt.org/z/sW3dn6

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