65919


以下のサイトを参考に、MFCでアプリケーションを終了したときのアプリケーションの座標を取得し、再度アプリケーションを起動したときに前回アプリケーションを終了したときの座標にアプリケーションを起動させる処理を作っていますが、以下の参考サイトにある、

[code]

    LPTSTR pBuff = csInifile.GetBuffer(MAX_LEN + 1);
    
[/code]

という処理が何のためにしているかをちゃんと理解したくて質問させて頂きました。

参考にしているサイト：  
<http://pg-sample.sagami-ss.net/?eid=29>

これを理解するために私なりにしたことは、  
まずバッファが何かよく分からなかったので、調べました。  
結果、コンピュータとハードディスクなど、処理速度に大きな差があるときに、コンピュータが一時的にデータを溜めこんで、ハードディスクに読み書きをしている間に待ち時間が発生しないようにするための仕組みだと理解しました。

しかし、なぜ上記の`GetBuffer`の処理でパスの文字列を作るためにバッファを作る必要があるか分かりませんでした。分からない理由は、パスの文字列を作るだけならコンピュータとハードディスクに処理速度は関係なくすぐに作れるのでは？と思ったからです。

ただ、仮説としては、コンピュータとハードディスクに処理速度の差は圧倒的で、パスを`GetModuleFileName`で作るだけでもバッファがないと本当にコンマ数秒くらい遅延するのかと思いました。(しかしながら、ただ単に`GetModuleFileName`の第二引数の型が`LPTSTR`なので、`CString`型である`csInifile`を`LPTSTR`にキャストすることがメインの目的で`GetBuffer`を使用されているのかもしれませんが...)

上記、教えて頂けるとありがたいです。どうかよろしくお願いします。


CC BY-SA 4.0
2020-04-23T21:55:25.777
65902
2020-04-24T06:11:47.890
2020-04-24T00:18:32.257
2238
21034
question
c++ mfc
ファイル名の文字列を作る処理でGetBufferを使ってバッファを取得する意味が分からない


バッファに対する理解が誤っています。Wikipediaの[バッファ](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%83%E3%83%95%E3%82%A1)には

> 情報処理機器におけるバッファ・緩衝（域）（英: buffer）とは，記憶単位間のデータ転送において一時的にデータを記憶することを指す。

と説明しています。「何の」バッファであるかが重要であり、質問者さんは誤解しています。ハードディスク等は無関係であり、[GetBuffer](https://docs.microsoft.com/en-
us/cpp/atl-mfc-shared/reference/csimplestringt-
class?view=vs-2019#getbuffer)の説明には

> Returns a pointer to the internal character buffer for the CSimpleStringT
> object.

とあるように、文字通り、「文字の」バッファを得るものです。文字のバッファが無ければGetModuleFileNameで得られる文字列を格納できません。


CC BY-SA 4.0
2020-04-23T22:49:03.923
65903
2020-04-24T02:40:30.947
2020-04-24T02:40:30.947
4236
4236
65902
answer


いくつか誤解と言うか「理解不足」があります。

**バッファについて**

コンピュータのソフトウェア用語として使われるバッファは、少し長めに言うと「(○○のための)バッファ(用のデータ(メモリ)領域)」になるでしょう。  
カッコ内の部分は記述されることもあるし省略されることもあります。まあ省略されることが多いでしょうが。

ハードディスクに係わる仕組みは大きな1例であって全てではありません。  
@sayuri さん回答のように、「何の」ためのバッファか、については使われ方によってそれぞれ違い、目的は山のように存在します。

質問記事の場合は以下に説明しますが、処理を速くするのが目的ではありません。

**ファイル名の文字列を作る処理？**

質問タイトルの「ファイル名の文字列を作る処理」そのものは間違ってはいないのですが、その4行の処理も2行づつ別々の処理に分けることができます。

質問にも引用された行を含む最初の2行は、現在のプロセス(自分自身のプログラム)の実行可能ファイルのパスを文字列変数に取得します。  
2行目の[GetModuleFileNameW function](https://docs.microsoft.com/en-
us/windows/win32/api/libloaderapi/nf-libloaderapi-
getmodulefilenamew)の第2、第3パラメータには、パスを格納するバッファへのポインタとそのバッファのサイズを指定する必要がありますし、そのバッファは`GetModuleFileName`を呼び出す前に確保されている必要があります。

しかし、`CString csInifile`変数はクラスメンバとして定義されているだけであり、
**この時点ではこの変数に空文字列を示す終端の0くらいしかデータは存在しておらず、パスを格納するのに十分なバッファは確保されていません。**

そのため、 **「実行可能ファイルのパスを格納するバッファ」を`MAX_LEN + 1`文字の長さを指定して確保するために行っている**
、というのが質問の処理です。

確保した後、実行可能ファイルのパスを取得するために`GetModuleFileName`を呼び出しています。

そしてその次の2行が狭義の「ファイル名の文字列を作る処理」であり、実行可能ファイルのパスの最後の`exe`を`ini`に書き換えて、iniファイル名のパスを作っています。

**最終的にiniファイル名のパスを格納しておく`CString`変数があるので、作業用として実行可能ファイルのパスを格納するバッファの確保も、その変数の`GetBuffer`メソッドで行っているのでしょう。**

行数も変わらないしあまり意味はありませんが、`MAX_LEN`のサイズが小さいなら`GetBuffer`を使わずに自動変数としてバッファを定義して使う以下のような方法も考えられます。  
参照記事に定義された`2048`くらいでも問題無く動作するでしょう。

[code]

    TCHAR pBuff[MAX_LEN + 1];
    DWORD PathLen = GetModuleFileName(NULL, pBuff, MAX_LEN) - 3;
    errno_t ernt = _tcscpy_s(&pBuff[PathLen], (MAX_PATH - PathLen), _T("ini"));
    csInifile = pBuff;
    
[/code]


CC BY-SA 4.0
2020-04-24T06:11:47.890
65919
2020-04-24T06:11:47.890
26370
65902
answer