_snprintf_s
の動作について自信がもてなかったので整理した。
まずは定義
本物とは引数名を変えて、自分用にわかりやすく書いてみる。
int _snprintf_s(
char *buf,
size_t buf_size,
size_t limit_size,
const char *format,
...
);
以降、上記を前提に書く。
limit_size の働き
**limit_size != _TRUNCATE
**を指定すると、生成文字列の長さがlimit_size
を越えた場合はlimit_size
までで切り詰められて'\0'
が付与される。
それでもbuf_size
を越える場合はエラー1になるが、これはbuf_size - 1
よりも大きなlimit_size
を指定してしまったマヌケなケースということになる。
**limit_size == _TRUNCATE
**を指定すると、生成文字列の長さがbuf_size
に収まらない場合にbuf_size - 1
までで切り詰められて'\0'
が付与される。
つまりlimit_size == buf_size - 1
としたのと同じ動作だ。
戻り値
切り詰め不要の場合、戻り値は生成文字列の長さ(\0
を含まない)になる。
切り詰めが発生した場合、戻り値は-1
になる。
つまり一般的な使い方は
limit_size
に_TRUNCATE
を指定しておき2、-1
が返った場合に切り詰められたことを知ればよい3。のだと思う。
ちなみに、limit_size
の無いsprintf_s(char *buf, size_t buf_size, format, ...)
では生成文字列の長さがbuf_size
を越えた時点でエラー1になる。切り詰めるなりして復帰してくれればよさそうなものなのに。「末尾_s
付きはセキュア関数」などと言ってもそれは「他人様の領域を壊さない」というだけで、本人は死んでいくのだ。
ところで _TRUNCATE とは
_TRUNCATE
の実体はsize_t
型にキャストされた-1
つまり64bit環境なら0xFFFFFFFFFFFFFFFF