アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんばんわ。
以下のようなchar型の配列を直接Fooにキャストして利用したいのですが、
Foo構造体のdataにはint型の配列として利用したいのですが可能でしょうか?
char型の配列を直接Fooにキャストした後にdataの部分を操作すれば
可能かと思っていたのですがうまくいきません。
foo->data=new int*[2];
としてしまうとbytData[8]が破壊されてしまいます。
このような方法は無理でしょうか?

struct Foo
{
   int   tenmp ;
   int   count ;
   int**  data ;
} ;

char bytData[ 4 + 4 + 8 ] = { 1, 0, 0, 0,
                2, 0, 0, 0,
                3, 0, 0, 0,
                4, 0, 0, 0,
} ;

int _tmain(int argc, _TCHAR* argv[])
{
   Foo*foo ;

   foo = reinterpret_cast< Foo* >( bytData ) ;

   foo->data = (int**)&bytData[ 8 ] ;// ここがダメ。

   printf( "%d\n", *foo->data[ 0 ] ) ;// 3
   printf( "%d\n", *foo->data[ 1 ] ) ;// 4

   return 0 ;
}

A 回答 (4件)

ポインタと配列の違いを、もういちどちゃんと勉強しなおした方がいいと思います。



foo = reinterpret_cast< Foo* >( bytData ) ;
の後では
 アドレスbyData : foo->tenmpの領域 : 値=0x00000001
 アドレスbyData+4 : foo->countの領域 : 値=0x00000002
 アドレスbyData+8 : foo->dataの領域 : 値=0x0000000400000003
となっています。
dataは int**ですから、 data[0] は 「dataの値が示すアドレスにある、 int *の値」 です。
 アドレス 0x0000000400000003 : foo->data[0]の領域: 仮に 0x1000000000000000 とする
*foo->data[ 0 ] とすれば、「上記のアドレスが示すアドレスにある、intの値」となります。
 アドレス 0x1000000000000000 : *foo->data[ 0 ]の領域: 仮に 0x000000010 とする
→ printf( "%d\n", *foo->data[ 0 ] ) ;// 0x000000010 = 16

foo->data=new int*[2]; では、 foo->dataの領域に、 new int*[2]の結果が代入されます。
new int*[2] で 0x2000000000000000 が確保されたとすると
 アドレスbyData+8 : foo->dataの領域 : 値=0x2000000000000000
よって
> bytData[8]が破壊されてしまいます
というのは当り前の現象です。


struct Foo
{
   int  tenmp ;
   int  count ;
   int  data[2] ;
} ;
と配列で宣言すると、dataとして int2個分の領域がFooの中に確保されます。

 アドレスbyData : foo->tenmpの領域 : 値=0x00000001
 アドレスbyData+4 : foo->countの領域 : 値=0x00000002
 アドレスbyData+8 : foo->data[0]の領域 : 値=00000003
 アドレスbyData+12 : foo->data[1]の領域 : 値=0x00000004
となる *** 可能性はあります ***
ですが
○sizeof(int)がいくつになるか?
○メンバがこの順番に並んでいるか?
○メンバが隙間無く並んでいるか?
○3,0,0,0 は 3なのか、0x03000000 なのか、それ以外なのか
といったことが、コンパイラ,CPU,OS,設定等によって違ってくることがあります。
精通している人が理解した上で、十分に注意して使う(でも使いたくない)裏技です。
// 特に、C++ではこれでは問題になることがあります
    • good
    • 0
この回答へのお礼

早々のご返答ありがとうございます。
とても参考になます。改めて勉強不足を実感しました。
また環境を書いていませんでした。大変失礼しました。

お礼日時:2015/01/22 09:27

いやいや, int が 4バイトかつ 4バイトアラインと仮定すれば


foo->data=new int*[2];
で「bytData[8]が破壊される」のは明らかでしょ? むしろ何をどう考えたら「破壊されない」と思えるのかが知りたいよ.

端的にいえば
int x = 1;
x = 2;
とやったときに「x が 1 のままでないのはおかしい」って思うか, ってことなんだけど....

ちなみに「メンバがこの順番に並んでいるか?」だけは (その場合) 規格で保証されているはずです>#3. 今の規格 (C++11 and/or C++14) を持っていないの「はず」としておくけど, C++98 でそうなってるしここを変える必然性はないと思うので今でも大丈夫じゃないかな. ほぼ「メンバが隙間無く並んでいるか?」も大丈夫だとは思うけどこっちが成り立つ必然性はない.
    • good
    • 0
この回答へのお礼

早々のご返答ありがとうございます。
とても参考になり、改めて勉強不足を実感しました。
また環境を書いていませんでした。
お手数をおかけして申し訳ありません。

お礼日時:2015/01/22 09:26

やるとすれば Fooの定義を



struct Foo {
  int tenmp;
  int count;
  int* data[1];
};

といった具合に定義してやる方法だと思います

Foo* foo;
foo = einterpret_cast< Foo* >( bytData );

// これは不要
// foo->data = (int**)&bytData[ 8 ] ;// ここがダメ。
  printf( "%d\n", *foo->data[ 0 ] ) ;// 3
  printf( "%d\n", *foo->data[ 1 ] ) ;// 4


WinAPIで使う BITMAPINFOのような使い方です …
    • good
    • 0
この回答へのお礼

早々のご返答ありがとうございます。
ビットマップを読み込んだことがありましたのでなるほどと思いました。

お礼日時:2015/01/22 09:27

不可能です。

    • good
    • 0
この回答へのお礼

早々のご返答ありがとうございます。
他の方の意見も踏まえて無理だと判断しました。

お礼日時:2015/01/22 09:28

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