プロが教える店舗&オフィスのセキュリティ対策術

void* a[2];
void* b = a;
void* c[2] = (void *[2])b;

error C2440: '型キャスト' : 'void *' から 'void *[2]' に変換できません。
配列型への変換はありませんが、参照またはポインタから配列への変換があります。

void*型にした a を再度void*型の配列に戻すにはどのように記述すればよいでしょうか?

環境はXP(SP3)のVS2008 MFC です。

宜しくお願いいたします。

A 回答 (8件)

void* a[2];


void* b;
void* (*c)[2];

b = (void*)a;
c = (void* (*)[2])b;

ってことですか?

この回答への補足

すみません。回答いただいてから気がつきました。
void* b = a;
ではなく、
void** b = a;
が正しいですね。

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

補足日時:2011/08/22 14:45
    • good
    • 0
この回答へのお礼

Tacosan様の以下と合わせて理解できました。ありがとうございました。

---
void *a[2];
void *b;
void *(*c)[2];
とすると void *(*)[2] は c の型であり, 同時に &a の型でもあります.
したがって上の場合
c = &a;
は文法的に全く正当です.
---

お礼日時:2011/08/23 13:27

二行目の式でaはvoidのダブルポインタなので


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

この回答への補足

すみません。回答いただいてから気がつきました。
void* b = a;
ではなく、
void** b = a;
が正しいですね。

キャストしなくても良いようですね・・・
仮にキャストしたい場合はどのようにしたらよいかありますでしょうか?

補足日時:2011/08/22 14:46
    • good
    • 0

void *a[2];


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

この回答への補足

すみません。回答いただいてから気がつきました。
void* b = a;
ではなく、
void** b = a;
が正しいですね。

キャストしなくても良いようですね・・・
仮にキャストしたい場合はどのようにしたらよいかありますでしょうか?

補足日時:2011/08/22 14:46
    • good
    • 0

(void* (*)[2])はvoid* [2]へのポインタです。



void* c[2];とすると、cはaと同じくvoid*の配列になるので、代入することができません。
なので、ポインタにしています。

そもそも、cをどのように使用したいのでしょうか?

この回答への補足

(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);
}

のような感じです。

補足日時:2011/08/22 15:20
    • good
    • 0

余談ですが


void *a[2];
void *b;
void *(*c)[2];
とすると void *(*)[2] は c の型であり, 同時に &a の型でもあります. したがって上の場合
c = &a;
は文法的に全く正当です. 見た人間は驚くかもしれませんが.

なお
「仮にキャストしたい場合はどのようにしたらよいかありますでしょうか?」
についてはどういう場面を想定しているかわからないのでパス. どういう式でどこにキャストを明示するときの話かが分かれば方法を書くかも.

この回答への補足

使用例は、

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);
}

のような感じです。

キャストを明示的にする意味はあまりなさそうですかね...

補足日時:2011/08/22 15:46
    • good
    • 0

キャストしますか?


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

この回答への補足

void* a[2];
void** b = a;
void* c[2] = (void*()[])b;

ということでしょうか?

error C2090: 関数は配列を返せません。
error C2066: 関数型へのキャストが正しくありません。
error C2440: '初期化中' : 'void **(__cdecl *)(void)' から 'void *[2]' に変換できません。
配列型への変換はありませんが、参照またはポインタから配列への変換があります。

となりました。

ダブルポインタです。
キャストはしなくてもよい気はしています。
なんだかふわふわした質問ですみません...

補足日時:2011/08/22 15:44
    • good
    • 0
この回答へのお礼

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

お礼日時:2011/08/23 13:25

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];

...

}

でいいような気がしますが。

この回答への補足

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

補足日時:2011/08/22 16:49
    • good
    • 0

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);
としないと本来はアウト.

この回答への補足

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

補足日時:2011/08/22 19:23
    • good
    • 0
この回答へのお礼

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

お礼日時:2011/08/23 13:24

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!