2

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);
4

1 回答 1

2

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

这是规格:

7.22.5.1 bsearch 函数

[...]

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

因此,第一个参数可以是指向 an 的指针,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

于 2021-02-10T00:54:23.060 回答