前提・実現したいこと
エディットボックスから特定の行の文字列を取得する方法を調べていたらエディットボックスにEM_GETLINEを送信すればいいという情報を見つけました。
その内容によると文字列を受け取るバッファの先頭2バイトにバッファのサイズを指定しておく必要があると書いてあり、その部分のソースコードは下のようになっていたのですが、(LPWORD)がなぜ必要なのか理由がわかりません。
試しに(LPWORD)を削除し*szBuf = sizeof(szBuf) / sizeof(TCHAR);として実行してみましたが実行結果は何も変わりませんでした。
この(LPWORD)は何をするためのものなのですか?
該当のソースコード
c
1TCHAR szBuf[256]; 2*(LPWORD)szBuf = sizeof(szBuf) / sizeof(TCHAR);
補足情報(FW/ツールのバージョンなど)
Microsoft Visual C++ 2010 Express C言語
WIN32 ユニコードビルド Windows7
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
ベストアンサー
余談ですが、このキャストは安全ではないです。
ref:
(翻訳)C/C++のStrict Aliasingを理解する または - どうして#$@##@^%コンパイラは僕がしたい事をさせてくれないの! - yohhoyの日記
やるとしたら
c
1TCHAR szBuf[256] = { 0 }; 2const WORD size = (WORD)(sizeof(szBuf) / sizeof(TCHAR)); 3memcpy(szBuf, size, sizeof(size));
じゃないでしょうか。
なんか無駄に回答者が多くついている割に、質問者の理解に繋がっていないようなので、真面目に回答します。
仮にTCHAR
がchar
だとしましょう。
c
1TCHAR szBuf[256]; 2*(LPWORD)szBuf = sizeof(szBuf) / sizeof(TCHAR);
szBuf
はTCHAR [256]
型の変数です。C言語では配列は3つくらいの例外を除いて式中では常に配列の先頭要素へのポインタとして扱われるのでした。
ポインタ型はつねにもととなる方があってそこから派生して作られます。
c
1int n = 0; 2int* np = &n;
この例ならnp
の型はint*
型ですが、これはint
型から派生してできますよね?
これは何を意味するかと言うと、pointerをdereferenceするときに(=たぐり寄せたとき)、メモリーをどう扱えばいいかを示すのが派生元の型である、ということができます。この例ではnp
をdereferenceしたときの領域の大きさ、bitの使われ方はint
型と同じだよ、といううのがint*
型の意味ですね。
c
1TCHAR szBuf[256]; 2*(LPWORD)szBuf = sizeof(szBuf) / sizeof(TCHAR);
さて、本題に戻りましょう。この配列(=szBuf
)の先頭要素へのポインタをLPWORD
型(=WORD*
型=16bitの符号なし整数型へのポインタ型)にキャストするというのはどういうことかというと、メモリーをどう扱えばいいかを偽る、という作業になります。配列szBuf
のメモリー領域は本当はTCAHR
の配列ですが、WORD
型の変数であると偽るわけです。
では質問者さんがいう
まだよくわからないのですが、szBuf[0]からszBuf[256]までの要素のそれぞれを2バイトの領域として扱い、szBuf[0]にsizeof(szBuf) / sizeof(TCHAR)の結果を保存するという意味であってますか?
は誤りなのでしょうか?じつはあながち間違いでもありません。(szBuf[256]
じゃなくてszBuf[255]
でしょうが、ケアレスミスですよね?)
Re:Cのポインタと配列の関係について考察してみる
を読んでいただきたいのですが、ポインタは単にdereferenceして指し示す先を取り出すだけではなくて、ポインタ演算によってポインタの指す場所を移動させる、イテレータのような機能も持つのでした。
c
1int n1 = 3; 2int arr[2] = { 0 }; 3int* p; 4p = &n1;//OK 5p++;//OK 6p = arr;//OK 7p++;//OK
言い換えるとint
型は要素数1の配列とみなすこともできるわけです。というかポインタには要素数の情報がありませんので、上のコードのような芸当ができるのでした。
つまり、
szBuf[0]からszBuf[256]までの要素のそれぞれを2バイトの領域として扱い
は正しく直すと
要素数不明のWORD
型の配列と偽る
となります。
で追記前に書きました話に戻ります。
先程
メモリーをどう扱えばいいかを偽る、という作業
と書きましたが、こういう作業はコンパイラがプログラムの最適化をしやすくするために、多くの場合で禁止されています。言い換えるとszBuf
は何も変更されないというコードをコンパイラが生成する可能性があるということです。
ではどうすればいいのか、細かい理屈は冒頭でリンクしていてこのコメント欄にも書き込みされている
yohhoyさんの記事を見ていただくとして、結論から言うとmemcpy
でbyte copyすればよいです。念の為memcpy
とは何をするものなのかman memcpy
でぐぐって確認すると
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/memcpy.3.html
memcpy() はメモリー領域 src の先頭 n バイトを メモリー領域 dest にコピーする。コピー元の領域と コピー先の領域が重なってはならない。重なっている場合は memmove(3) を使うこと。
とあります。
投稿2019/05/28 12:46
編集2019/05/29 17:21総合スコア5850
0
ユニコードビルドだとTCHAR=WCHARなので、(LPWORD)があってもなくてもバッファのサイズが格納される領域のバイト数は2バイトですが、マルチバイトビルドだとTCHAR=CHARなので、(LPWORD)がないと、バッファのサイズは先頭1バイトのみに入ってしまいます。
どちらのビルドモードでも意図した結果になるようにLPWORDでキャストしているのでしょう。
投稿2019/05/28 12:33
総合スコア3041
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
まずsizeof(szBuf) / sizeof(TCHAR)
で求められるのは数値になりますから、格納先のTCHARとは型が異なります。
TCHARの領域に数値型を代入しようとしているので、通常ならWarningが出て注意されるので、代入先はTCHAR型ではなくWORD型として扱ってね、とやっているわけです。
LPWORD型はWORD型のポインタです。
WORD型はshort型ですから2バイトです。
投稿2019/05/29 01:16
総合スコア16998
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/05/29 10:32
2019/05/29 11:05
2019/05/29 12:09
2019/05/29 17:22
2019/05/29 23:51
0
windowsのTCHARはANSIとUNICODEで型が変化し
それぞれ、char
とwchar_t
です。
というわけでchar
の場合で実験すると
c
1#include <stdio.h> 2 3typedef unsigned short *LPWORD; 4 5int main(){ 6 { 7 char szBuf[256] = {0x11,0x11,0x11,0x11}; 8 *(LPWORD)szBuf = sizeof(szBuf) / sizeof(char); 9 printf("%02x %02x %02x %02x\n", szBuf[0],szBuf[1],szBuf[2],szBuf[3]); 10 } 11 puts("------------"); 12 { 13 char szBuf[256] = {0x11,0x11,0x11,0x11}; 14 *szBuf = sizeof(szBuf) / sizeof(char); 15 printf("%02x %02x %02x %02x\n", szBuf[0],szBuf[1],szBuf[2],szBuf[3]); 16 } 17}
では出力される文字が変わります。
投稿2019/05/28 12:51
総合スコア15147
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/05/28 13:10
2019/05/28 15:29
2019/05/28 15:51
2019/05/28 15:53
2019/05/28 15:57
2019/05/28 15:58
2019/05/28 15:59
2019/05/28 16:13
2019/05/28 16:39
2019/05/29 16:47
2019/05/29 17:23
2019/05/30 10:45