GLib のドキュメントには、型変換マクロに関する章があります。 int
を*void
ポインタに変換することについての議論では、それは次のように述べています(強調は私のものです):
単純に、これを試すかもしれませんが、それは正しくありません。
gpointer p; int i; p = (void*) 42; i = (int) p;
繰り返しますが、その例は正しくありません。コピーしないでください。 問題は、一部のシステムではこれを行う必要があることです:
gpointer p; int i; p = (void*) (long) 42; i = (int) (long) p;
(出典:GLib 2.39.92のGLibリファレンスマニュアル、章 Type Conversion Macros )。
なぜlong
へのキャストが必要なのですか?
int
の必要な拡大は、ポインターへのキャストの一部として自動的に行われるべきではありませんか?
C99: 6.3.2.3
の見積もりによると:
5整数は任意のポインタ型に変換できます。以前に指定された場合を除き、結果は実装定義であり、正しく整列されていない可能性があり、参照されたタイプのエンティティをポイントしていない可能性があり、トラップ表現である可能性があります。56)
6ポインタ型は整数型に変換できます。前述の場合を除き、結果は実装定義です。結果を整数型で表現できない場合の動作は未定義です。結果は、整数型の値の範囲内である必要はありません。
link のドキュメントによると、
ポインタのサイズは常に32ビット以上です(すべてのプラットフォームでGLibがサポートする予定です)。したがって、ポインタ値には少なくとも32ビットの整数値を格納できます。
そしてさらに long
は少なくとも32ビットであることが保証されています 。
したがって、コード
gpointer p;
int i;
p = (void*) (long) 42;
i = (int) (long) p;
gLibで宣伝されているように、より安全で移植性が高く、32ビットまでの整数に対してのみ明確に定義されています。
これは、この変換が実装依存であるためだと思います。特定の実装ではポインタ型のサイズであるため、この目的にはuintptr_t
を使用することをお勧めします。