为什么bsearch会返回空白*?

时间:2011-10-29 10:36:42

标签: c pointers const void bsearch

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

如果我传入const void * basebsearch也不应该返回const void *个结果?

3 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分: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限定并修改指向对象是合法的本身未被宣布为const

在过去,我假设另外限制限定指针参数会强制执行不变性,但仔细重读第6.7.3.1节会让我相信情况并非如此:指向对象的约束 - 如果指针实际用于访问对象,则限制限定指针才会生效,但调用代码不能单独从原型中做出假设...

答案 2 :(得分: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