修飾子を指す型に追加することは暗黙的な変換ですが、修飾子を削除するには明示的なキャストが必要です。
のプロトタイプは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 修飾を削除するために使用できることを意味します。
int *q = bsearch(&needle, bar, 42, sizeof *bar, cmpi);
これは完全に合法です。未定義の動作は、実際q
に modifiy を使用した場合にのみ発生しますbar
。
また、ポインター パラメーターの const 修飾は、キャストなしで受け入れられる引数にのみ影響を与えますが、関数がポイント先の object を変更しないことを保証するものではないことにも注意してください。これは、事実上すべての既存のコードが従う規則にすぎませんが、言語のセマンティクスによって強制されるわけではありません。
特に、コンパイラはこの情報を呼び出しコードの最適化に使用することはできません。コンパイラは関数本体を確認する必要があります。これは、オブジェクト自体が変更されていない場合、ポインタから const 修飾を削除して、指定されたオブジェクトを変更することが合法であるためです。宣言されてconst
います。
以前は、ポインター引数をさらに制限修飾すると不変性が強制されると思っていましたが、セクション 6.7.3.1 を注意深く読み直すと、そうではないことがわかりました。制限修飾されたポインターは、ポインターが実際にオブジェクトにアクセスするために使用されている場合にのみ有効になりますが、呼び出しコードはプロトタイプだけからその仮定を行うことはできません...