いつもお世話になります。
よろしくお願い致します。
環境VC++6.0
Windows XP
下記のバイナリーデータを読込んで10進に変換します。
バイナリーデータ16進
56 08 C6 62 4E 42 8F F3-33 49 A8 72 B0 3F 57 08
#int nByteSizeには取得するバイト数1or2が入る
// 構造体の実体化 及びメモリー領域確保
COOR_STR *pstrCoorXY;
pstrXY = (COOR_STR* ) malloc(sizeof(COOR_STR) * nNumOfData);
// データを読み込む
ReadFile(hF, chBuf, sizeof(chBuf), &dwResult, NULL);
for(count = 0; count < 5 ; count++)
{
// バイナリデータを格納
memcpy(chDataX, &chBuf[nX], nByteSize);
memcpy(chDataY, &chBuf[nY], nByteSize);
// データを変換およびセット
pstrXY->m_lX = (long)chDataX[0];
pstrXY->m_lY = (long)chDataY[0];
pstrXY++;
}
chDataXに56,chDataYに08と1バイトはpstrXY->m_lXに86,pstrXY->m_lYに8と
上手く取れるのですが chDataXに56 08,chDataYにC6 62と2バイトをいれても
pstrXY->m_lXには1バイトしかセットされません。
理由は (long)chDataX[0]; だからなんですが、格納した2バイトを
pstrXY->m_lXセットするにはどうすればいいでしょうか。
これだけの問題ではなく、もしかしたらバイナリーデータの取得方法のやり方
がおかしいのでしょうか。
デバックウィンドウのメモリーを見ますと
chDataXのアドレス 0x0012f3cc には56 20 と入っていますのでビックエンディアンと理
解しています。
どなたかご教授お願い致します。
long*型にキャストして入れるか、long型変数にmemcpyするかしてできないでしょうか?
> memcpy(chDataX, &chBuf[nX], nByteSize);
// nByteSizeが何ものか?nXって?ループの中では同じ値を指し続けているか?
memcpy(&pstrXY->m_lX, &chBuf[nX], sizeof(long));
あ~すいません。
> // nByteSizeが何ものか?
は
>nByteSizeには取得するバイト数1or2が入る
にありましたね。
となると、1バイトの時もありうるならば、memcpy の前に明確に初期化処理が必要か
も。
Blueさんありがとうございます。
for(count2 = 0; count2< nCoorCount; count2++)
{
memset(chDataX,'\0',sizeof(chDataX)); // chDataX を初期化
memset(chDataY,'\0',sizeof(chDataY)); // chDataY を初期化
で初期化処理はしています。
nXは取得するバイトの先頭をさしています。
書き忘れましたがfor文の最後でこのように場所移動させています
nDaiSize はバイト(1 or 2バイト)すうによってかわるので可変です。
pstrXY++;
nX = nX + nDaiSize; // データ位置カウントアップ(X)
nY = nY + nDaiSize; // データ位置カウントアップ(Y)
1バイト時
nXの初期値は0で 0バイト目から1バイトを取得するので 56を指す
nYの初期値は1で 1バイト目から1バイトを取得するので 08を指す
2バイト時
nXの初期値0で 0バイト目から2バイトを取得するので 56 08を指す
nYの初期値2で 2バイト目から2バイトを取得するので C6 62を指す
バイナリーデータも実際には256バイトあります
説明不足で済みません。
で、もう回答は書いたつもりなんですけど。
pstrXY->m_lX = 0;
pstrXY->m_lY = 0;
memcpy( &pstrXY->m_lX, &chBuf[ nX ], nByteSize );
memcpy( &pstrXY->m_lY, &chBuf[ nY ], nByteSize );
一応わかりやすいSample)
char s[ 2 ] = { 0x56, 0x08 };
long l;
l = 0;
memcpy( &l, &s[ 0 ], 2 );// 2134
l = 0;
memcpy( &l, &s[ 0 ], 1 );// 86
メモリ上でlongのデータがどのように配置されているかをきちんと理解していれば、
答えは出ると思いますよ。
この部分でまだうまく処理がかけないというのはその部分の理解が足りないからです。
メモリ上のlongやshortのデータがどのように配置されているのかをデバッガ等で
確認してみてください。また、メモリコピーがどのようにデータをコピーしているのかも
きちんと抑えておくべきです。
> long*型にキャストして入れるか
これ大間違いでした。sizeof( long ) == 4 の環境ではまずかったです。
sizeof( short ) == 2 の環境であるならば、2バイトの値を取得するときは
unsigned short* でキャストして取得ですね。
char s[ 2 ] = { 0x56, 0x08 };
long l;
// 2バイト
l = *( ( unsigned short* )&s[ 0 ] );
// 1バイト
l = *( ( unsigned char* )&s[ 0 ] );
Blueさん丁寧な説明ありがとうございます。
PATIOさんアドバイスありがとうございます。
Blueさんのを参考にして下記のように解決しました。
for(count = 0; count< 5; count++)
{
// 初期化
pstrXY->m_lX = 0;
pstrXY->m_lY = 0;
// バイナリデータを格納
memcpy(&pstrXY->m_lX, &chBuf[nX], nByteSize);
memcpy(&pstrXY->m_lY, &chBuf[nY], nByteSize);
pstrXY++;
nX = nX + nDaiSize; // データ位置カウントアップ(X)
nY = nY + nDaiSize; // データ位置カウントアップ(Y)
}
ちなみに、malloc した領域は free しないのですかね?
まぁしなくても、プログラムが終われば、システムが解放してくれますけど。
freeするときはmalloc関数の戻り値を指定しないといけないので、
>pstrXY = (COOR_STR* ) malloc(sizeof(COOR_STR) * nNumOfData);
>pstrXY++;
のように、malloc関数の戻り値を書き換えて使っているようですと、freeするときに
進めた分ポインタを戻すような作業が必要になります。
配列のように
pstrXY[ 0 ]
というようにアクセスするか、free用にmalloc関数の戻り値を保持する変数をもう1つ
用意するようにしたほうがいくらか簡単です。