web-dev-qa-db-ja.com

voidポインタのキャスト

私は古いCコードで次のことをたくさん見ました:

_type_t *x = (type_t *) malloc(...);
_

_void *_なので、malloc()から返されたポインターをキャストする意味は何ですか?古いCコンパイラがvoidポインタをサポートしておらず、代わりにmalloc()が_char *_を返すために使用されていたためですか?

17

あなた自身の説明は正しいものです。以前のANSIC( 'K&R' C)には、暗黙的な変換を伴うvoid *タイプがありませんでした。 char *は疑似void *型を兼ねていますが、型キャストの明示的な変換が必要でした。

最新のCでは、mallocのプロトタイプが欠落している場合のコンパイラの警告を抑制できるため、キャストは嫌われています。 C++では、キャストが必要です(ただし、ほとんどの場合、newの代わりにmallocを使用する必要があります)。

更新

キャストが必要な理由を説明しようとする以下の私のコメントは少し不明確でした。ここでそれをよりよく説明しようと思います。 mallocchar *を返す場合でも、次のようなものであるため、キャストは必要ないと思われるかもしれません。

int  *a;
char *b = a;

ただし、この例ではキャストも必要です。 2行目は、単純代入演算子(C99 6.5.1.6.1)の制約違反です。両方のポインタオペランドは互換性のあるタイプである必要があります。これを次のように変更すると:

int  *a;
char *b = (char *) a;

制約違反がなくなり(両方のオペランドのタイプがchar *になりました)、結果が明確に定義されます(charポインターに変換するため)。 「逆の状況」の場合:

char *c;
int  *d = (int *) c;

同じ引数がキャストにも当てはまりますが、int *の配置要件がchar *よりも厳しい場合、結果は実装定義になります。

結論:ANSI以前の時代には、mallocchar *を返し、結果をキャストしないことは '='演算子の制約違反であるため、型キャストが必要でした。

23
schot

ここでの問題は、Cのどの方言とも互換性がありません。問題はC++です。 C++では、voidポインターを他のポインター型に自動的に変換することはできません。したがって、明示的なキャストがないと、このコードはC++コンパイラでコンパイルされません。

6
slacker

Mallocがchar *を返したことがあることを私は知りません。

ただし、void *からtype_t *(またはその他のタイプ)への暗黙的なキャストが常に許可されているわけではありません。したがって、適切なタイプに明示的にキャストする必要があります。

3
abelenky