_stprintf_sの第2引数

解決


淡水魚  2007-06-29 17:57:13  No: 65536

よろしくお願いします。
.NET2005  ユニコードライブラリで、TCHER型を使う場合、  

TCHER tch[10];
_stprintf_s( tch1, 20, _T("値は%dです"), 20 );

というように、第2引数にバッファサイズを置かないといけないと思っていて、実際にビルドは通らなかった記憶があります。
ネット検索をしてみても、バッファサイズが必要だと書いてあります。

ところが、昨日、なにげに

_stprintf_s( tch1, _T("値は%dです"), 20 );

としたら、通ってしまいました。
ブレークポイントを置いて見ても、値は正しく代入されています。

どこかで私が初歩的な勘違いをしているのかもしれませんが、
なにかご存じの方がいらしたら、アドバイス頂けませんでしょうか。


Blue  2007-06-29 18:16:24  No: 65537

_stprintf_sのリファレンスをご覧になりましたか?

C++言語であれば、第一引数がTCHAR型配列であれば
templateをつかう_stprintf_s関数が呼ばれます。
(そのなかでtemplateをつかわない_stprintf_s関数が呼ばれる)


淡水魚  2007-06-29 21:01:48  No: 65538

Blueさん、ありがとうございます。

実は、初心者で、「_stprintf_sのリファレンス」の見方が分りません。
MSDNやネットでいろいろ検索してみましたが、見つけることができませんでした。

不思議なのは、以前使った時はバッファサイズが必要だったのに、今回はなくても通ってしまうことです。
.NET2005で、全く同じように作成したはずなのに、その違いが起きた原因が分かりません。


Blue  2007-06-29 21:28:15  No: 65539

http://search.microsoft.com/results.aspx?setlang=ja-JP&mkt=ja-JP
で検索してください。

>不思議なのは、以前使った時はバッファサイズが必要だったのに、今回はなくても通ってしまうことです。
>.NET2005で、全く同じように作成したはずなのに、その違いが起きた原因が分かりません。
ですからtemplateのおかげです。
配列であれば要素数を取得することが出来るのです。

template <size_t size>
int sprintf_s(
   char (&buffer)[size],
   const char *format [,
      argument] ... 
); // C++ only

sizeに値が取れる。


淡水魚  2007-06-30 13:44:26  No: 65540

Blueさん、ありがとうございます。
目的のページはヒットしました。
でも、「理解しました」には、ほど遠いと思います。

>不思議なのは、以前使った時はバッファサイズが必要だったのに、今回はなくても通ってしまうことです。
>.NET2005で、全く同じように作成したはずなのに、その違いが起きた原因が分かりません。
ですからtemplateのおかげです。

全く同じように開発環境でアプリケーションを新規作成して、自動的にテンプレート宣言が行われる場合と、そうでない場合があるのでしょうか。
初心者で、templateを意識したことはあまりなく、特別なコードの追加もしていません。


Blue  2007-07-02 07:23:14  No: 65541

同じ_stprintf_sを使うにしても前述どおり引数の型に依存します。

たとえば、

TCHAR str[256];
である場合
_stprintf_s(str, _T("%d"), 10);
でも
_stprintf_s(str, sizeof(str) / sizeof(str[0]), _T("%d"), 10);
でもどちらでもOKですが、

TCHAR str[256];
TCHAR* p = str; // もしくは p = new TCHAR[256]; 等
である場合に第一引数にpを指定するとTCHAR配列型ではなくTCHARポインタ型であるため
_strprintf_s(p, 256, _T("%d"), 10);
のパターンの呼び出ししかできません。
(C言語のみの場合はtemplate自体がないのでサイズを指定するしかない)

おそらく、以前はサイズを指定しなければならなかったというのは、
第一引数にTCHAR配列型ではなく、TCHARポインタ型を指定していたのではないのでしょうか?

>自動的にテンプレート宣言が行われる場合と、そうでない場合があるのでしょうか
は、C++言語の場合同じ関数名でも引数の型や数が違えば違う関数として
解釈されるので、自動的に宣言が増えるとかそういうことはないと思われます。
(あるとすれば、C言語かC++言語かだけでしょう。)


Blue  2007-07-02 07:33:09  No: 65542

一応、サンプル的なコード。
※VC6ではコンパイルできません。

// 引数としてint型で配列数が10の配列のポインタを指定する
void A(int (*n)[10]) {}

// 引数としてint型で配列数が10の配列の参照を指定する
void B(int (&n)[10]) {}

// 引数としてint型で配列数がsizeの配列の参照を指定する
template<size_t size>
void C(int (&n)[size]) {}

// 引数としてint型のポインタを指定する(配列型ではない)
void D(int* p) {}

int main()
{
    int n1[10], n2[20];
    
    A(&n1);
    //A(&n2); // C2664(配列数が合わないため型が不一致)

    B(n1);
    //B(n2);  // C2664(配列数が合わないため型が不一致)

    C(n1);
    C(n2);

    D(n1);
    D(n2);

    return 0;
}


淡水魚  2007-07-04 00:32:42  No: 65543

たいへんありがとうございました。

理解できたと思います。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加