問題タブ [void-pointers]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - C の void ポインターへのポインター - 基本的なポリモーフィズムに void** を使用できますか?
a がメモリ内でどのように見えるかは理解できますvoid**
が、それを正しく使用しているかどうか疑問に思っています。以下に説明する内容に根本的な欠陥はありますか? たとえば、「自分には合っている」とは言えますが、何らかの方法で悪い/移植性のないコードを作成していませんか?
だから私は小惑星のクローンを持っています。弾丸を発射できるエンティティは、プレイヤー ( SHIP *player_1
、SHIP *player_2
) と UFO ( UFO *ufo
) の 3 つです。弾丸が発射されたとき、誰が弾丸を発射したかを知ることが重要です。プレーヤーの場合、何かに当たったときにスコアを増やす必要があります。したがって、箇条書きには、それが属するエンティティの種類 ( owner_type
) と、所有者への直接のポインタ( ) が格納されますowner
。
次に、プレイヤーがボタンを押すか、UFO がターゲットを検出すると、次の関数のいずれかが呼び出されます。
...たとえば、次のように呼び出すことができます。
最後に、弾丸がターゲット (小惑星など) に命中すると、所有者を逆参照します。船の場合は、その場でスコアをインクリメントできます。
それは合理的なアプローチだと思いますか?私が言うように、それは私にとってはうまくいきますが、C の経験は数か月しかありません。
最後の注意: なぜ a のvoid*
代わりに a を使用しないのvoid**
ですか? ダングリングポインターを避けたいからです。言い換えれば、player_1
死んで解放されたが、弾丸は進み続けて小惑星に衝突したとします。しかない場合void*
、関数はそれが割り当て解除されたメモリを指してhit_asteroid
いることを知る方法がありません。bullet->owner
しかし、 を使用するとvoid**
、それが NULL かどうかを有効に確認できます。player_1
が NULL の場合は、これ*bullet->owner
も NULL になります。
編集:これまでのすべての回答者は、(たとえば、ベースオブジェクトを静的に割り当てるだけで) ダングリングポインターの問題を回避できるため、ここではおそらく void** を使用する必要はないことに同意しています。それらは正しいので、リファクタリングします。しかし、メモリ割り当て/キャストなどの点で何かを壊す可能性のある方法で void** を使用したかどうかを知りたいと思っています。しかし、誰も手を空中に投げ出して欠陥を宣言しなかったとしたら、少なくとも技術的には機能するものに似ていると思います.
ありがとう!
c++ - Ncursesユーザーポインタ
私はncursesを学ぼうとしていて、ここで素晴らしいガイドを読んでいますが、ユーザーポインターの例はコンパイルされません。コンパイルしようとすると、このエラーが発生します。
menu.cpp: In function 'int main()':
menu.cpp:44: error: invalid conversion from 'void (*)(char*)' to 'void*'
menu.cpp:44: error: initializing argument 2 of 'int set_item_userptr(ITEM*, void*)'
menu.cpp:70: error: invalid conversion from 'void*' to 'void (*)(char*)'
また、strlenとcallocでコンパイルするには、おそらくcstdlibとcstringを追加する必要があります。
ボイドポインタについてはよくわからないので、例を修正するのに役立つ情報をいただければ幸いです。
ありがとう
c - GLibアトムとメモリチャンク
次のコードスニペットは、公式GNOME2開発者ガイドからのものです。
これは、すべてのアトムが42バイトであり、各「メモリチャンク」に
42個の16アトムが含ま40000/16=2500
れ、上記のコードを実行するとメモリチャンクが作成されることを意味しますか?なぜここでgchar*を使用しているのですか?が実行されると、gpointer(void *)からgchar *への暗黙のキャストが行われ
data[i] = g_mem_chunk_alloc(my_chunk);
ますか?上記のステートメントが当てはまる場合、各gchar*は42バイトのメモリを指します。では、特定のアトムのすべてのバイトにアクセスするにはどうすればよいですか?
data[7]+41
使用可能なメモリロケーションになりますか?
コードをコンパイルしようとすると、gccは次のエラーメッセージを生成します。
error: storage size of ‘my_chunk’ isn’t known
どうしたの?
c++ - 多重継承: void * から 2 番目の基本クラスにキャストした後の予期しない結果
私のプログラムは、動的呼び出しの状況でデータまたはオブジェクトを転送するために void* を利用する必要があるため、プリミティブ型であっても任意の型のデータを参照できます。しかし、最近、複数の基本クラスを持つクラスの場合にこれらの void* をダウンキャストするプロセスが失敗し、メモリアドレスが正しいように見えても、これらのダウンキャストされたポインターでメソッドを呼び出した後にプログラムがクラッシュすることさえあることを発見しました。「vtable」へのアクセス中にクラッシュが発生します。
そこで、小さなテスト ケースを作成しました。環境は Mac OS X の gcc 4.2 です。
次の出力が生成されます。
ご覧のとおり、「Decorated (per void*)」の結果は完全に間違っています。また、最初の行のように 30,30 にする必要があります。
shape_cast() でどのキャスト方法を使用しても、装飾されたパーツに対して常に同じ予期しない結果が得られます。これらの void * には完全に問題があります。
私のC++の理解から、これは実際に機能するはずです。これを void* で動作させる機会はありますか? これは gcc のバグでしょうか?
ありがとう
c - Cの動的データ型としてvoid*を使用するモジュラーコードに関するいくつかの質問
数日前、私はこの質問を投稿しました、そして、誰もが私に使用するように提案しましたvoid*
、それは私がしました。それらのいくつかは私が世話をする必要があるいくつかのことも指摘したと思いますが、それらが正確に何であったかはわかりません。しかし、私はこれに関していくつかの問題を抱えています...
非常に大きいコードをすべて投稿するのではなく、重要だと思うものを投稿します。うまくいけば、あなたが私を助けてくれるのに十分です。
私のハッシュテーブル構造は次のようなものです。
私の挿入関数の署名は次のようになります。
そして、その関数内のどこかで、ハッシュテーブルに空きバケットが見つかったら、次のようにします。
これにはいくつかの問題があります。
1)上記のように、フリーバケットの各キー/値ペアを、キー/値hashInsert
関数の引数として渡されたのと同じポインターに設定しているだけです。すでにお気づきかもしれませんが、これは問題を引き起こします...たとえば、次のようなことをします。
また、入力が「KeyA」、次に「KeyB」の場合、両方のバケットキーとして「KeyB」が使用されます。キーだけでなく値にも同じことが当てはまります。これは、どのデータ型でもコードを完全にモジュール化するため、基本的に同じ型であるためです。
どうすればこれを解決できますか?
私の最初は、それを使用strdup(str)
して関数に渡すことhashInsert
です。それで問題は解決します。また、これはメインコードで処理されたmalloc()
ため、値として渡す必要のある他のデータ型にも簡単に使用できます(キーはおそらく常に文字列または整数になります)。
しかし、この解決策には別の問題があります...
2)この割り当てられたメモリをどのように解放する必要がありますか?確かに、それは「ハッシュテーブルモジュールプログラマー」ではなく「メインプログラマー」によって割り当てられたので、「メインプログラマー」はメインコードでそれを解放する必要がありますよね?しかし、それは私にはモジュラーコードのようには見えません。
私のコードにはhashDestroy
、割り当てられたすべてのメモリを解放する機能もあります。しかし、どうすればこの関数を使用してすべてを解放できますか?すべてのキー/値を繰り返し処理して使用することはできません。そもそもfree()
それらの一部はmalloc'd
プログラマーによるものではなく、解放する必要がないためです。
hashDestroy
解放しなければならないものと解放してはいけないものをどのように見つけることができますか?
3)最後に、この問題をミックスに入れることもできると思います...ポイント1で、私の提案は、その特定の問題を使用strdup()
またはmalloc
「修正」することでしたが、それはあまりモジュール化されていないように見えます私に。このメモリ割り当ては、「メインプログラマ」によるメインコードではなく、ハッシュテーブルモジュールコードで行う必要があります。
私がこれを解決することをどのように提案しますか?つまり、データ型は何でもかまいません。を使用すると非常にstrdup()
役立ちますが、文字列に対してのみ機能します。特定の構造またはintだけにメモリを割り当てる必要がある場合はどうなりますか?
大きな投稿で申し訳ありませんが、これらの質問はすべて関連していると思います。私のCの知識はそれほど極端ではないので、それらを理解するのに助けが必要です。私は最近そのことを知りましvoid*
た...
com - ATL と IUnknownPtr を使用する場合のキャストの正しい方法は何ですか?
既存の ATL COM オブジェクトを変更しているときに、「The Old New Thing」ブログの「The way people mess up IUnknown::QueryInterface」という記事に出くわし、コメント セクションで議論が始まりました。回答者 (Norman Diamond) は、記事の例の 1 つで、void** へのキャストが間違っていることを指摘しました。
ただし、コードを修正してキャストを適切に実行しようとすると、メモリリークが発生します。
例は次のとおりです。
ノーマンは言った
パンクはボイドではない*. punk は IUnknown* です。
void** はユニバーサル ポインター型ではありません。void* はユニバーサル ポインター型であり、char* と相対はそのように等価になるように祖父母化されますが、void** はそうではありません。
呼び出し規則に従い、恐ろしい死を回避したい場合は、次のようにする必要があります。ボイド *パンクボイド; psf->QueryInterface(IID_IUnknown, &punkvoid); パンク = (IUnknown *) パンクボイド;
他の多くの MSDN 貢献者も同じ過ちを犯しました....現在までのすべての VC++ 実装で機能すると言う人もいるかもしれませんが、それは正しいコードにはならず、呼び出し規則にまだ違反しています。
これに照らして、古いコードを変更しました-次のとおりです。
次に、次のように変更しました。
しかし今、私のアプリケーションには、この COM オブジェクトからのメモリ リークがあります。
c++ - C ++のwindow.setTimeout()と同等
javascriptには、1000ミリ秒後に非同期で呼び出さwindow.setTimeout( func, 1000 ) ;
れるこの甘くて甘い関数があります。func
C ++で(マルチスレッドなしで)同様のことをしたいので、次のようなサンプルループをまとめました。
どうすればこのような作品を作ることができますか?
c - 関数の引数としてvoidポインタを使用する際の問題
この結果がわかりません...
コード:
そして、私はこの呼び出しを行います:bar(900011009);
しかし、printf()
出力は次のとおりです。
私は本当にkey
voidポインタである必要があります、どうすればこれを修正できますか?
c - C: void ポインターから型を推定する
関数が引数として void ポインターを取るとします。たとえば、int func(void *p);
p が指している型をどのように判断または推測できますか?
c++ - C++のボイドポインタ
私はこのqsortを書きました:
私がこれを呼ぶとき
char**からvoid**への無効な変換を示しています。なぜこれが間違っているのですか?
これはコードです: