次のコードの「const」によって引き起こされる動作、特にキャスト:
const void *foo()
{
void *bar = NULL;
// Assign bar to some address here.
return (const void *)bar;
}
キャストは必要ですか?コンパイラは、キャストを実行しない限り、型が戻り値の型と一致しないという警告を出しますが、結果の動作は異なりますか?
キャストは必須ではなく、役に立たないことさえあります。キャストしない場合、Cは警告を必要としません。
戻り値が期待されるchar *
ときにを返すことができます。const char *
これは他のタイプにも当てはまります。aが期待されるT *
ときにを返すことができます。const T *
Cは、return
ステートメントについて次のように述べています。
(C99、6.8.6.4p3)「式が、それが現れる関数の戻り型とは異なる型を持っている場合、値は、関数の戻り型を持つオブジェクトに割り当てられたかのように変換されます。」
char *
aをに割り当てることができますconst char *
(反対は無効であることに注意してください)。Cはポインタの割り当てについて次のように述べています。
(C99、6.5.16.1p1)「次のいずれかが当てはまります。[...]両方のオペランドは、互換性のある型の修飾バージョンまたは非修飾バージョンへのポインターであり、左側が指す型には、指す型のすべての修飾子があります。右に;[...]」
const void *foo()
を返すことを宣言する関数を定義していますconst pointer
。したがって、コンパイラは戻り値の型がconst void *
したがって、キャスト。
ただし、ポインターの値を計算しているときは、契約を破っています-実際に戻っvoid *
ているので、正しい変更は宣言を修正してを削除することをお勧めしますconst
(したがって、キャストの必要性を取り除きます)
キャストがないと、constであるはずのポインタが返されます。したがって、リターンタイプは一致しません。呼び出し元はconstvoid*を受け取ります(これは戻り型であるため)。したがって、キャストを実行することでコンパイラの警告を取り除くことができますが、キャストを実行するときは、自分が何をしているかを確認する必要があります。あなたがコンパイラに言っているからです(私は私が何をしているのか知っています、私に警告しないでください)。