4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

_snprintf_s の動作

Last updated at Posted at 2017-01-16

_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


  1. 無効なパラメタに対応するエラーハンドラが呼ばれる。デフォルトだとたぶんダイアログが出て死ぬ 2

  2. どうせ大概limit_size == buf_size - 1で事足りるだろう

  3. 死ぬことなく知ることができる

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?