将限定符添加到指向类型是一种隐式转换,而删除限定符需要显式转换。
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 节让我相信情况并非如此:对指向的对象施加的约束-to by restrict-qualified pointers 只有在指针实际用于访问对象时才生效,但调用代码不能仅从原型做出该假设...