私は次のCパズルに出会いました:
Q:IA-64では次のプログラムがセグメンテーション違反になりますが、IA-32では正常に動作するのはなぜですか?
int main()
{
int* p;
p = (int*)malloc(sizeof(int));
*p = 10;
return 0;
}
64ビットマシンのint
のサイズは、ポインターのサイズと同じでない場合があることを知っています(int
は32ビットで、ポインターは64ビットです)。しかし、これが上記のプログラムにどのように関係しているかはわかりません。何か案は?
_int*
_へのキャストは、適切な_#include
_がない場合、malloc
の戻り値の型がint
であると想定されるという事実を隠しています。 IA-64にはsizeof(int) < sizeof(int*)
が含まれているため、この問題が明らかになります。
(未定義の動作のため、sizeof(int)==sizeof(int*)
が真であるプラットフォームでも失敗する可能性があることに注意してください。たとえば、呼び出し規約が整数よりもポインターを返すために異なるレジスタを使用した場合)
comp.lang.c FAQ には なぜmalloc
からの戻り値をキャストする必要がないのか、潜在的に悪い についてのエントリがあります。
最も可能性が高いのは、含まないmalloc
のヘッダーファイルであり、コンパイラが通常これを警告する一方で、戻り値を明示的にキャストしているという事実は、 「何をしているのか知っていると伝えている。
これは、コンパイラがint
からmalloc
が返されることを期待していることを意味しています。それらが異なるサイズである場合、それはあなたを悲しませます。
これがneverがmalloc
をCにキャストする理由です。void*
が返すことは暗黙的に正しい型のポインターに変換されます(ヘッダーを含めていない場合は、安全でない可能性のあるintからポインターへの変換について警告しているはずです)。
これが、プロトタイプの欠落に関する警告なしにコンパイルしない理由です。
これが、Cでmallocリターンをキャストしない理由です。
C++との互換性のためにキャストが必要です。省略する理由はほとんどありません(ここでは理由はありません)。
C++の互換性は常に必要なわけではなく、いくつかのケースではまったく不可能ですが、ほとんどの場合、非常に簡単に実現できます。