10
void * bsearch ( const void * key,
                 const void * base,
                 size_t num,
                 size_t size,
                 int ( * comparator ) ( const void *, const void * ) );

如果我传入 a const void * base,不应该bsearch也返回const void *结果吗?

4

3 回答 3

8

当您搜索某些内容时,这是一个有效的请求,您可以在找到它后对其进行修改。如果搜索功能不允许您这样做,那就太严格了。当然,这样的修改可能会破坏后续搜索,但这是另一回事。

参数是 const 作为 bsearch本身不会修改它们的承诺,这是合理的。

于 2011-10-29T10:41:45.197 回答
3

将限定符添加到指向类型是一种隐式转换,而删除限定符需要显式转换。

的原型的bsearch()编写方式允许以下两种用法而无需显式强制转换:

int needle = 0xdeadbeef;

int foo[42] = { ... };
int *p = bsearch(&needle, foo, 42, sizeof *foo, cmpi);

const int bar[42] = { ... };
const int *q = bsearch(&needle, bar, 42, sizeof *bar, cmpi);

然而,这意味着可以使用bsearch()- 以及许多其他 libc 函数 - 在没有警告的情况下删除 const-qualification,例如,如果我们编写了

int *q = bsearch(&needle, bar, 42, sizeof *bar, cmpi);

这是完全合法的:未定义的行为只有在我们实际习惯于修改时才会q发生bar

您还应该记住,对指针参数进行 const 限定只会影响哪些参数在没有强制转换的情况下被接受,但不能保证函数不会修改指向的对象。这只是几乎所有现有代码都遵循的约定,但它不是由语言语义强制执行的。

特别是,编译器不能使用此信息在调用代码中进行优化 - 编译器需要查看函数体,因为如果对象本身不是,则从指针中删除 const 限定并修改指向的对象是合法的t 宣布const

过去,我假设对指针参数进行额外的限制限定会强制执行不变性,但仔细重新阅读第 6.7.3.1 节让我相信情况并非如此:对指向的对象施加的约束限制限定的指针只有在指针实际用于访问对象时才生效,但调用代码不能仅从原型做出这种假设......

于 2011-10-29T12:03:16.003 回答
0

我认为这是 C 的类型系统中最大也是最烦人的缺陷。另一个例子是strchr,一个具有完全相同问题的函数:它返回一个指向用户传入的资源的指针。这个函数需要对 const 和非 const 输入参数都有用。你看到的是一种妥协。

我发现这样的访问者最烦人:

const struct list *list_next(const struct list *x) { return x->next; }

对于内部使用,宏是一个很好的“多态”实现

#define LIST_NEXT(x) ((x)->next)

但是对于外部使用,您必须使用bsearch折衷或两个单独的功能list_nextlist_next_const.

于 2011-11-12T22:33:26.100 回答