Decremented Blog

プログラミング、釣り、工作など、ジャンルを特に定めず、適当に書かれたブログです。

[C++] C++における printf の恐怖

2009-01-29 00:24:26 | プログラミング・開発
前回の記事で、CStringを利用しないことで高速化する内容を書きました。
実装としては、CStringを自作の文字列クラスに置き換えた訳ですが、ちょっと困ったことになりました。

具体的には、sprintfやTRACE使用時、文字列クラスを文字列型にキャストして渡さないと、正常に出力できなくなりました。
具体的には、以下のような感じです
(CMyString は文字列のラッパクラスで、char *への変換オペレータを持つとします)
// 文字列クラス
CMyString str ="Test";

// 動かない
printf("%s", str);

// 動く
printf("%s", (char *)str);

理由としては単純で、可変長引数が型情報を持たないため、正常に型変換オペレータが呼ばれないためです。
つまり、printfには、strの内容がそのまま渡されます。
(構造体の値渡しと同じで、メンバ変数のメモリ領域がそのままコピーされます)

大抵、文字列クラスにはメンバ変数として文字列ポインタ以外に長さなどの情報を持っており、それらもコピーされてしまうため、正常に動作しません。
MFC/ATLのCStringでは、メンバ変数を文字列へのポインタだけにすることで解決してるようです。
メンバ変数がポインタのみのため、sizeof(CString)を見てみると4となっていることが分かります。

自作の文字列クラスもそのようにすれば良いのですが、用途の都合上、メンバとして固定長の文字列バッファを持っているため、不可能です。
いっそ、C++用のsprintfを作ってしまえばよいのですが、さすがに面倒です。
C++なら、可変長引数を使わなくても、暗黙変換と既定の引数をを使えば、実行時にちゃんと型チェックする安全なsprintfが実現できそうですが・・・