古い C コードでは、次のようなことがよくあります。
type_t *x = (type_t *) malloc(...);
malloc()
から返されたポインターをキャストするポイントは何void *
ですか? 古い C コンパイラが void ポインタをサポートしておらず、代わりmalloc()
に返していたからchar *
でしょうか?
古い C コードでは、次のようなことがよくあります。
type_t *x = (type_t *) malloc(...);
malloc()
から返されたポインターをキャストするポイントは何void *
ですか? 古い C コンパイラが void ポインタをサポートしておらず、代わりmalloc()
に返していたからchar *
でしょうか?
あなた自身の説明は正しいものです。void *
ANSI C より前 ('K&R' C) には、暗黙的な変換を伴う型がありませんでした。char *
疑似void *
型として倍増しましたが、型キャストの明示的な変換が必要でした。
現代の C では、 のプロトタイプが欠落しているというコンパイラの警告を抑制することができるため、キャストは嫌われていますmalloc
。C++ では、キャストが必要です (ただし、ほとんどの場合、new
代わりに使用する必要がありますmalloc
)。
キャストが必要な理由を説明しようとする以下の私のコメントは少し不明確でした。ここでよりよく説明しようとします. malloc
を返す場合でもchar *
、キャストは次のように似ているため、必要ないと考えるかもしれません。
int *a;
char *b = a;
ただし、この例ではキャストも必要です。2 行目は、単純代入演算子 (C99 6.5.1.6.1)の制約違反です。両方のポインター オペランドは、互換性のある型である必要があります。これを次のように変更すると:
int *a;
char *b = (char *) a;
制約違反がなくなり (両方のオペランドが typechar *
になりました)、結果が明確に定義されます (char ポインターに変換するため)。「逆の状況」では:
char *c;
int *d = (int *) c;
同じ引数がキャストにも当てはまりますが、int *
より厳密なアラインメント要件がある場合char *
、結果は実装定義になります。
結論: ANSI より前の時代には、malloc
返さchar *
れた結果をキャストしないことは「=」演算子の制約違反であるため、型のキャストが必要でした。
ここでの問題は、C の方言との互換性がないことです。問題はC++です。C++ では、void ポインターを他のポインター型に自動的に変換することはできません。したがって、明示的なキャストがなければ、このコードは C++ コンパイラでコンパイルされません。
malloc が char* を返したことは知りません。
しかし、void* から type_t* (またはその他の型) への暗黙的なキャストが常に許可されているわけではありません。したがって、適切な型に明示的にキャストする必要があります。
void * であるため、malloc() から返されたポインターをキャストするポイントは何ですか?
まったく逆です。void ポインターを使用する前に、実際の型にキャストする必要があります。これは、avoid *
はその場所に格納されているデータについて何も意味しないためです。