C の型キャストについて質問があります。
void *buffer;
(int *)((int)buffer);
この型キャストは何をしていますか? そして、何をして((int)buffer)
いますか?
私のような Linux/x86-64 コンピューターを使用していると想像してください。次に、ポインターは 64 ビットで、int
幅は 32 ビットです。
したがって、buffer
変数はある場所に初期化されています。おそらく 0x7fff4ec52020 (おそらく 内のローカル変数のアドレスである可能性がありますmain
)。
キャスト(int)buffer
は、おそらく最下位の 32 ビット、つまり 0x4ec52020 の int を返します。
で再度キャストすると(int*)((int)buffer)
、有効なメモリを指していない偽のアドレス 0x000000004ec52020 が返されます。その偽のポインターを逆参照すると、SIGSEGV が発生する可能性が非常に高くなります。
そのため、一部のマシン (特に私のもの)では;と同じ(int *)((int)buffer)
ではありません。(int*)buffer
幸いなことに、ステートメントとして、(int *)((int)buffer);
目に見える副作用はなく、コンパイラーによって (最適化を要求した場合) 最適化されます (それを「削除」することによって)。
したがって、そのようなコードは大きな間違いです (たとえば、そのポインターを逆参照すると、未定義の動作になる可能性があります)。元のコーダーがここで説明する奇妙なセマンティクスを本当に意図していた場合は、コメントを追加する必要があります (そのようなコードは移植できません)。
おそらく#include
-ing<stdint.h>
およびintptr_t
orを使用uintptr_t
すると、より理にかなっている可能性があります。
Let's see what the C Standard has to say. On page 55 of the last freely published version of the C11 standard http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf we have
5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.
What does this mean in your example? Section 6 says that the cast (int)buffer
will compile, but if the integer is not big enough to hold the pointer (which is likely on 64-bit machines), the result is undefined. The final (int*)
casts back to a pointer.
Section 5 says that if the integer was big enough to hold the intermediate result, the result is exactly the same as just casting to (int*) from the outset.
In short the cast (int)
is at best useless and at worst causes the pointer value to be lost.
ストレートな C コードでは、これは意味がありません。なぜなら、変換void*
は暗黙的だからです。以下は問題なくコンパイルされます
int* p = buffer;
さらに悪いことに、このコードはエラーを引き起こす可能性があります。64 ビット プラットフォームの場合を考えてみましょう。への変換int
は、ポインターを 32 ビットに切り捨ててから、int*
. これにより、ポインター値が切り捨てられ、確実にエラーが発生します。