• ベストアンサー

void*型の配列について

void* a[2]; void* b = a; void* c[2] = (void *[2])b; error C2440: '型キャスト' : 'void *' から 'void *[2]' に変換できません。 配列型への変換はありませんが、参照またはポインタから配列への変換があります。 void*型にした a を再度void*型の配列に戻すにはどのように記述すればよいでしょうか? 環境はXP(SP3)のVS2008 MFC です。 宜しくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

void* a[2]; void* b; void* (*c)[2]; b = (void*)a; c = (void* (*)[2])b; ってことですか?

suke326
質問者

お礼

Tacosan様の以下と合わせて理解できました。ありがとうございました。 --- void *a[2]; void *b; void *(*c)[2]; とすると void *(*)[2] は c の型であり, 同時に &a の型でもあります. したがって上の場合 c = &a; は文法的に全く正当です. ---

suke326
質問者

補足

すみません。回答いただいてから気がつきました。 void* b = a; ではなく、 void** b = a; が正しいですね。 で、すみません、 void* (*) はどのような意味なのでしょうか? 参考になるURLなど教えていただけませんか? 呼び方がわからないので検索できませんでした。

その他の回答 (7)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.8

void* p[2]; のとき p の型は void *[2] であり, これに対して配列からポインタへの変換を適用すると void ** となります. だから AfxBeginThread の呼び出しを今のままにするなら, barThread の中では bar((void **)p); のようにキャストすれば十分だし, 受け取る bar の方も void bar(void **p) { HANDLE handle = *(HANDLE*)p[0]; HANDLE event = *(HANDLE*)p[1]; // 以下略 } でいいはず. 逆に, bar を今のままにするなら foo における AfxBeginThread の呼び出しを AfxBeginThread(barThread, &p); としないと本来はアウト.

suke326
質問者

お礼

勉強になりました。ありがとうございました。

suke326
質問者

補足

そうですね。仰られる通り、 void bar(void **p) とし、 *(HANDLE*)p[0]; とするのが自然ですね。

回答No.7

AfxBeginThreadの引数等がLPVOIDというのが引っかかってるんでしょうか? handleとeventは、変更する必要はなさそうなんですが。変更しないのであれば、ポインタにする必要もないので、 HANDLE h[2] = {handle, event}; AfxBeginThread(bar, (LPVOID)h); として、 void bar(LPVOID p) { HANDLE* ph = (HANDLE*)p; HANDLE handle = ph[0]; HANDLE event = ph[1]; ... } でいいような気がしますが。

suke326
質問者

補足

すみません。例が良くなかったですね。 ポインタにする必要がある場合と仮定していただけると幸いです。 お手数おかけしてすみません。

  • hrsmmhr
  • ベストアンサー率36% (173/477)
回答No.6

キャストしますか? やっぱりダブルポインタでしょうか? ひょっとしたらvoid*()[]で通るかもしれませんが 少なくとも配列の長さは入れても意味がないと思います。

suke326
質問者

お礼

勉強になりました。ありがとうございました。

suke326
質問者

補足

void* a[2]; void** b = a; void* c[2] = (void*()[])b; ということでしょうか? error C2090: 関数は配列を返せません。 error C2066: 関数型へのキャストが正しくありません。 error C2440: '初期化中' : 'void **(__cdecl *)(void)' から 'void *[2]' に変換できません。 配列型への変換はありませんが、参照またはポインタから配列への変換があります。 となりました。 ダブルポインタです。 キャストはしなくてもよい気はしています。 なんだかふわふわした質問ですみません...

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

余談ですが void *a[2]; void *b; void *(*c)[2]; とすると void *(*)[2] は c の型であり, 同時に &a の型でもあります. したがって上の場合 c = &a; は文法的に全く正当です. 見た人間は驚くかもしれませんが. なお 「仮にキャストしたい場合はどのようにしたらよいかありますでしょうか?」 についてはどういう場面を想定しているかわからないのでパス. どういう式でどこにキャストを明示するときの話かが分かれば方法を書くかも.

suke326
質問者

補足

使用例は、 void bar(void*(*p)[2]) { ULONG addr = 0x10; ULONG data = 0; HANDLE handle = *(HANDLE*)(*p)[0]; HANDLE event = *(HANDLE*)(*p)[1]; while(data == 0){ read(handle, addr, &data); } SetEvent(event); } UINT barThread(void* p) { bar((void*(*)[2])p); return 0; } void foo(HANDLE handle, HANDLE event) { void* p[2]; p[0] = &handle; p[1] = &event; AfxBeginThread(barThread, p); } のような感じです。 キャストを明示的にする意味はあまりなさそうですかね...

回答No.4

(void* (*)[2])はvoid* [2]へのポインタです。 void* c[2];とすると、cはaと同じくvoid*の配列になるので、代入することができません。 なので、ポインタにしています。 そもそも、cをどのように使用したいのでしょうか?

suke326
質問者

補足

(void* (*)[2])の意味はなんとなくわかるのですが、もっと深く知りたかったのでお聞きしました。 使用例は、 void bar(void*(*p)[2]) { ULONG addr = 0x10; ULONG data = 0; HANDLE handle = *(HANDLE*)(*p)[0]; HANDLE event = *(HANDLE*)(*p)[1]; while(data == 0){ read(handle, addr, &data); } SetEvent(event); } UINT barThread(void* p) { bar((void*(*)[2])p); return 0; } void foo(HANDLE handle, HANDLE event) { void* p[2]; p[0] = &handle; p[1] = &event; AfxBeginThread(barThread, p); } のような感じです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

void *a[2]; void *b = a; void **c = b; ということ?

suke326
質問者

補足

すみません。回答いただいてから気がつきました。 void* b = a; ではなく、 void** b = a; が正しいですね。 キャストしなくても良いようですね・・・ 仮にキャストしたい場合はどのようにしたらよいかありますでしょうか?

  • hrsmmhr
  • ベストアンサー率36% (173/477)
回答No.2

二行目の式でaはvoidのダブルポインタなので bはvoidのダブルポインタの型でないといけなくて そうすればcはキャストしないでもよいのではないでしょうか?

suke326
質問者

補足

すみません。回答いただいてから気がつきました。 void* b = a; ではなく、 void** b = a; が正しいですね。 キャストしなくても良いようですね・・・ 仮にキャストしたい場合はどのようにしたらよいかありますでしょうか?

関連するQ&A

  • void*の型キャストについて質問です

    VisualStudio 2008 を使ってOpenCVを勉強中なのですが、 … IplImage *dst; … cvRelease(&dst); をすると、 error C2664: 'cvRelease' : 1 番目の引数を 'IplImage **__w64 ' から 'void **' に変換できません。(新しい機能 ; ヘルプを参照) と出ます。 確か、void*はどの型からでも明示型キャストは必要なかったと思うのですが、これはVisual Studio 2008 の仕様ですか?

  • C言語の型と配列

    char* str[10]={"a","b"}; char* str2="c"; としたときにstr=str2とすると 型が合わないといったエラーが出ます。 でもstrって結局はポインタの配列の先頭要素のアドレスですよね。 ポインタにポインタを入れているので通るのかなと思ったんですけど、 配列で宣言するとポインタにも型がつくのでしょうか? この例だと strは char * を10個持つ配列をさすポインタ  で、 str2はchar *をさすポインタ みたいなかんじです。 質問の意味がわかりにくいですが、ご指摘をいただければ補足しますので よろしくお願いします。

  • C言語のvoid型ポインタを使いたいのですが…

    C言語のvoid型ポインタを使いたいのですが… 関数の引数として、void型ポインタを使おうと思ったのですが、内部でどのように処理すればいいのかわかりません キャストすれば問題なく使えるとのことですが、どの型でキャストするのかをどのように判断するのかがわかりません 具体的には、画像処理で画像の構造体をいくつか作ったのですが、それぞれの構造体ごとに関数を書くと関数が多くなるので、void型ポインタでまとめてつくろうとしています どのように型の判断を行えばいいのかを教えてください

  • void型のポインタで構造体の参照

    void型のポインタで構造体や共用体を参照することはできますか? void *p=&kou; struct KOU kou; (struct KOU*)kou.name="名前"; のようにして構造体を参照しようとしたのですが、「左側が構造体又は共用体ではありません。」と出ます。型キャストはコンパイラに型を知らせるだけのものなのでコンパイラが構造体の型を知ることができない、ということでしょうか?void型のポインタを使って構造体(共用体)を参照することはできますか?回答よろしくお願いします。

  • C++配列の型に関するC++規格について教えていただきたいです。

    C++配列の型に関するC++規格について教えていただきたいです。 以前にYahoo知恵袋でも質問しましたが、答えが得られませんでしたので、こちらでも質問させていただきたいと思います。 ※以下、質問になります。(分かり難いかも知れませんが宜しくお願い致します。) 環境は、Visual Studio 2010 (C++) です。 std::fill_n() で次のような警告がでましたので、調べていましたところ、 ...\xutility(2801): warning C4996: 'std::_Fill_n': Function call with parameters that may be unsafe - ... 次のような定義方法を見つけました、 typedef char (&std::tr1::_No)[1]; ↑このような定義方法があることを初めて知りました。 ちなみに、std::fill_n() は次のようになりました。 long data[32]; std::fill_n(data, 32, 0); ←正常 long* p_data = data; std::fill_n(p_data, 32, 0); ←warning long (&a_data)[32] = data; std::fill_n(a_data, 32, 0); ←正常 知りたいのは、配列を関数に渡すときに、 通常は、void func(long* pd); のようにポインタで渡すと思います。 また、void func(long pd[]); や void func(long pd[32]); もポインタの場合と同じになりますが、型保証がありません。 これはC++規格で規定されていることだと思います。 次のようにすると、型保証がされますが、この記法がC++の規格として規定されているかを知りたいです。 1. void func(long (&ad)[32]); // 関数呼び出しは、func(data); 2. void func(long (*pd)[32]); // 関数呼び出しは、func(&data); また、通常のポインタで配列を渡すことを、配列の参照渡し?と言うと思いますが、 この1,2,は何渡し?と言われるのでしょうか? #長い文になって申し訳ありませんが、宜しくお願い致します。

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • voidについて

    voidはデータの定義の無い型であり、代入演算子で代入する場合に、データとして参照するvoid型のメモリの領域は、代入先として参照するvoid以外の型のメモリの領域の型に変換されるという事でしょうか。

  • 関数のパラメータに配列を渡すときは、非参照型が普通なんですか?

     LippmanのC++プライマー(第4版)を勉強中です。 p.274以降に、配列に作用する関数の定義法と使用法に関する解説があり、p.275に以下の記述があります。 ■配列アーギュメント  配列パラメータも参照型と非参照型がある。  普通、配列は非参照型にする  非参照型パラメータは対応するアーギュメントのコピーで初期化される。配列アーギュメントはその配列の先頭要素へのポインタであり、そのポインタがパラメータにコピーされる。関数はアーギュメントのポインタを変更することはないが、パラメータのポインタを使って配列要素を変更することはできる。 ■配列を参照で渡すこと  配列パラメータを配列への参照にすることもできる。パラメータが配列への参照である場合、コンパイラは配列アーギュメントをポインタに変換しない。配列への参照そのものを渡す。この場合、配列の大きさはパラメータの型の一部である。コンパイラは配列アーギュメントの大きさがパラメータの大きさに一致するかどうかチェックする。 しかしp.268の「ヒント」には以下のように記されています。 ヒント:  Cの素養があるC++プログラマはアーギュメントにアクセスするためにポインタを渡すことに慣れている。 C++では、参照パラメータを使うのが安全かつ自然である。  配列パラメータも参照で渡したほうが、ポインタをコピーしないですむし、配列の大きさを越えてアクセスすることによる実行時エラーも抑止できるので、いいように思いますが、なんで「普通、配列は非参照型にする」んでしょうか?

  • C言語:void*の指す型の比較をする方法

    C言語において、Java言語で言うところのinstanceof演算子の様な、方の比較をする演算子、もしくは、その方法をご存知でしたら教えていただきたく思います。つまり、   void型のポインタ変数x   void *x = (何とかのアドレス); となっている時、xの指す型・構造体を知りたいのです。 問題の解決方法・アドヴァイスを宜しくお願いします。 私は現在 void *function(..., ...); という関数を作り、それは処理に応じて,A構造体へのポインタ、B構造体へのポインタ又は、NULLを返します。そして、 void *tmp = function(..., ...); を作りました。tmpがAを指している時、Bを指している時、NULLとなっている時、それぞれに合わせて異なった処理をしたく思っています。そのためには、tmpがどの構造体又は、NULLを指しているのかが分からないといけません。その方法が分からず困っています。

  • 多次元配列とポインタ渡しについて

    多次元配列のポインタ渡しについて,自分で検索したのですがあまりにも様々で具体的な記述が無く質問させていただきました. 検索力不足もあるのでソースの提示だけでも結構ですので,ご回答お願いいたします. OS:Windows XP ソフト:VisualStudio.net2003(C++) C++プログラミング暦2ヶ月弱です. データを変換して多次元配列にデータを入れる自作の関数をつくりたいと考えています. 具体的には,a1からa2,b1からb2を10区間に分けてたデータを配列にしたいといったものです. 自分で記述した関数は以下の通りです. void Convert(float a1,float a2,float b1,float b2,unsigned short *Data){ int k; float a; float b; for(k=0;k<11;k++){ a = a1 + (a2 - a1) / 10; b = b1 + (b2 - b1) / 10; Data[k][1] = ( powf(2.0,16) * (a + 10.0) / 20; Data[k][1] = ( powf(2.0,16) * (b + 10.0) / 20; } } void main(){ float a = 10; float b = 20; unsigned short Data[11][2]; Convert(a1,a2,b1,b2,Data); ... } としています. ここでコンパイルすると, "5番目の引数をunsigned shortからunsigned short *に変換できません" となってしまいます. 配列の名前のみの部分はその配列の先頭アドレスを示すポインタであることから,自分では間違いがないと思っているのですが….

専門家に質問してみよう