void*
Cおよび派生言語の便利な機能です。たとえば、void*
Objective-CオブジェクトポインタをC++クラスに格納するために使用できます。
私は最近型変換フレームワークに取り組んでいましたが、時間の制約のために少し怠惰でした-それで私は使用void*
しました...それがこの質問が出てきた方法です:
intをvoid*に型キャストできるのに、floatをvoid *にできないのはなぜですか?
void*
Cおよび派生言語の便利な機能です。たとえば、void*
Objective-CオブジェクトポインタをC++クラスに格納するために使用できます。
私は最近型変換フレームワークに取り組んでいましたが、時間の制約のために少し怠惰でした-それで私は使用void*
しました...それがこの質問が出てきた方法です:
intをvoid*に型キャストできるのに、floatをvoid *にできないのはなぜですか?
BOOLはC++型ではありません。おそらくtypedefであるか、どこかで定義されており、これらの場合、intと同じになります。たとえば、WindowsのWindef.hには次のようなものがあります。
typedef int BOOL;
だからあなたの質問はになります、なぜあなたはintをvoid *に型キャストすることができますが、floatをvoid *にしないことができますか?
int to void *は問題ありませんが、表現が本質的に同じであるため、一般的には推奨されません(一部のコンパイラーは警告します)。ポインタは基本的に、メモリ内のアドレスを指す整数です。
float to void *は、float値の解釈とそれを表す実際のビットが異なるため、問題があります。たとえば、次の場合:
float x = 1.0;
これは、32ビットメモリを00 00 80 3f(IEEE単精度での浮動小数点値1.0の実際の表現)に設定します。フロートをボイド*にキャストすると、解釈があいまいになります。メモリ内の位置1を指すポインタを意味しますか?または、メモリ内の位置3f800000(リトルエンディアンを想定)を指すポインタを意味しますか?
もちろん、2つのケースのどちらが必要かが確実な場合は、問題を回避する方法が常にあります。例えば:
void* u = (void*)((int)x); // first case
void* u = (void*)(((unsigned short*)(&x))[0] | (((unsigned int)((unsigned short*)(&x))[1]) << 16)); // second case
ポインタは通常、マシンによって内部的に整数として表されます。Cを使用すると、ポインタ型と整数型の間を行き来することができます。(ポインター値は、それを保持するのに十分な大きさの整数に変換され、元に戻される場合があります。)
void*
型にはまらない整数値を保持するために使用します。言語が機能することは保証されていませんが、だらしなく、Intelやその他のありふれたプラットフォームに自分自身を制約したい場合は、基本的にはすり減ります。
事実上、あなたがしていることはvoid*
、ポインタのためにマシンによって使用されるバイト数の一般的なコンテナとして使用することです。これは、32ビットマシンと64ビットマシンで異なります。したがって、に変換long long
するvoid*
と、32ビットプラットフォームではビットが失われます。
浮動小数点数に関しては、その意図(void*) 10.5f
はあいまいです。10.5を整数に丸めてから、それをナンセンスポインタに変換しますか?いいえ、FPUで使用されるビットパターンをナンセンスポインタに配置する必要があります。これは、を割り当てることで実現できますがfloat f = 10.5f; void *vp = * (uint32_t*) &f;
、これは単なるナンセンスであることに注意してください。ポインタはビットの汎用ストレージではありません。
ちなみに、ビット用の最適な汎用ストレージはchar
配列です。言語標準は、メモリがを介して操作できることを保証しますchar*
。ただし、データアライメントの要件に注意する必要があります。
標準では、752整数は任意のポインタ型に変換できるとされています。ポインタフロート変換については何も述べていません。