1

値への実際のポインターを送信するのではなく、値をポインターにキャストします。これらの例は、GTK プログラムの GUI インターフェイス コードで見つかりました。

g_signal_connect (pastebutton[pane],
                  "clicked",
                  G_CALLBACK(on_paste_button_pressed),
                  (void*)((long)pane<<4));

上記の例では、 の最後のパラメーターを参照していますg_signal_connecton_paste_button_pressedGTK2 によって呼び出されると、次のように void ポインターをキャストし直しますon_paste_button_presseduser_data

int pane = ((long)user_data) >> 4;

実際には、この特定の例をコードに追加しましたが、既存のものに基づいています。キャストに関する警告を避けるために、ビットシフトを追加しました。プログラム自体には、多数のウィジェットを含む 4 つのペインがあり、コピーと貼り付けのボタンを使用して、あるペインから別のペインにすべての値をコピーできます。

値をポインタアドレスにキャストするこの方法はよく使用されますか?また、これを使用しない理由はありますか?

編集:

整数から void ポインターへのキャストも、次のように実行できます。

void* void_ptr = some_int - NULL;
4

7 に答える 7

3

使用されます。必要なことを行うときに非常に一般的に使用されます。

これを使用しない理由の1つは、理論的にはポインタサイズがソース整数サイズよりも小さい可能性があることです。

これを使用しないもう1つの理由は、1つの整数データのみをコールバックに渡すことができるためです。将来、別のデータを追加する(または非整数に切り替える)必要がある場合は、コールバックが渡されたデータにアクセスするすべての場所を見つけて書き換える必要があります。したがって、将来データを拡張しなければならない可能性がある場合は、 (現時点でstruct1つしか保持されていない場合でも)を作成し、そのへのポインターを渡すことをお勧めします。intstruct

ただし、その単一の整数以外のものを渡す必要がなく、整数がに収まることが確実な場合はvoid *、この手法が破られることはありません。

PS Pedantallyに言えば、CもC ++も、整数からvoid *から整数への変換のラウンドトリップ保証を持っていないようです。つまり、CもC ++が機能し、元の整数値を復元することを保証しません。

于 2009-12-21T14:57:42.087 に答える
3

マクロ GINT_TO_POINTER() および GPOINTER_TO_INT() を使用して、ポインターと整数の間でキャストする必要があります。

glib: 型変換マクロ

于 2009-12-21T15:14:31.963 に答える
1

整数をポインターにキャストすると、値を値ごとに渡すことができます。これは、コンパイラがポインターを逆参照する必要がないため、参照パラメーターが必要な場合に推奨される方法です。

オーバーフローが発生する可能性があるため、ビットシフトはお勧めできません。

本当に移植可能なコードの場合は、整数型として intptr_t を使用する必要があります。これは、ポインターにうまく収まるためです。

于 2009-12-21T14:48:24.777 に答える
0

使用感はありますが、持ち運びには不向きなので注意が必要です。

C 標準では、ポインタ型が少なくとも整数型と同じ数のビットを持つことを義務付けていないため、常にそうできるとは限りません。

しかし、ポインターが実際に整数よりも小さいプラットフォームを思い出すことができないため、おそらく安全です(技術的に安全ではありませんが)。

キャストがそこにあると私が考えることができる唯一の理由は、アライメント警告の可能性を排除することです. C1x ドラフトのセクション 6.3.2.3 には、次のように記載されています。

整数は、任意のポインター型に変換できます。前に指定された場合を除き、結果は実装定義であり、正しく配置されていない可能性があり、参照された型のエンティティを指していない可能性があり、トラップ表現である可能性があります。

于 2009-12-21T14:48:20.280 に答える
0

このような場合に使用されます、はい。多くのプラットフォームで機能しますが、任意の整数が常に有効なポインター値であるとは限らないため、失敗する可能性がありますが、シフトを行うことでそれを回避できるはずです。また、整数が保持できるすべての値をポインターが保持できない可能性もあります。これは、ポインターが 32 ビットのプラットフォームで 64 ビットを使用している場合に当てはまります。longもちろん、値をシフトしているため、ポインターと整数が同じサイズであっても失敗する可能性があります。このトリックを使用する場合は、おそらくチェックする必要がありますsizeof (void*)使用する整数型のサイズに対して、実行時にポインターが十分に大きくない場合は実際の値に対してチェックします。これを完全に移植可能にして、それが必要なプラットフォームで実際のポインターを使用するのはおそらく価値がないので、このトリックが機能するプラットフォームに限定するか、トリックを完全に放棄してください。

于 2009-12-21T14:49:53.083 に答える
0

私はそれがうまくいくと思います。使用頻度の統計はありませんが、気にしますか?

ただし、ビットシフトがどのように役立つかはわかりません。

于 2009-12-21T14:50:11.553 に答える
0

これは C-FAQ からのものです。

Q:整数とポインターの間の変換はどのように行われますか? 一時的に整数をポインタに詰め込むことはできますか、またはその逆はできますか?

A: 昔々、ポインターを整数に変換できることが保証されていました (ただし、int と long のどちらが必要かはわかりませんでした)。 (十分に大きい) 整数に変換され、再び元に戻されても変更されず、変換 (およびマッピング) は「マシンのアドレス指定構造を知っている人にとって驚くべきことではない」ことを意図していた.いくつかの先例と整数/ポインタ変換のサポートがありますが、それらは常にマシンに依存しており、したがって移植性がありません。明示的なキャストは常に必要でした (ただし、初期のコンパイラはそれらを省略しても文句を言うことはめったにありませんでした)。

ANSI/ISO C 標準は、C が広く実装可能であることを保証するために、以前の保証を弱めています。ポインターから整数への変換および整数からポインターへの変換は実装定義であり (質問 11.33 を参照)、ポインターを変更せずに整数に変換したり元に戻したりできるという保証はもはやありません。

ポインターを整数に強制したり、整数をポインターに強制したりすることは、決して良い習慣ではありません。いずれかの種類のデータを保持できる汎用スロットが必要な場合は、ユニオンの方がはるかに優れています。

質問 4.15、5.18、および 19.25 も参照してください。

参考文献:K&R1 Sec. A14.4 p. 210 K&R2 秒 A6.6 p. 199 ISO秒。6.3.4 根拠セクション。3.3.4 H&S セクション 6.2.3 p。170、秒。6.2.7 171-2頁

于 2009-12-21T15:00:50.417 に答える