vsnprintf | Programming Place Plus C言語編 標準ライブラリのリファレンス

C言語編 標準ライブラリのリファレンス vsnprintf

先頭へ戻る

vsnprintf関数

概要 変換指定に沿って変換された文字列を、指定文字数以下だけ格納する。
ヘッダ stdio.h
形式 int vsnprintf(char* s, size_t n, const char* format, va_list args);
引数 s 結果を格納するメモリアドレス。
n 終端に書き込まれる '\0' を含めた、格納する最大文字数。
format 変換指定を含んだ、あるいは含まないプレーンな文字列。
args format に含まれている変換指定子に対応した、可変個引数リスト。
戻り値 実際に書き込まれた文字数(末尾のヌル文字を除く)を返す。エラーが発生した場合は、負数を返す。
仮に、戻り値が引数 n の値以上であったとすると、それは配列の大きさを超えて書き込みを行ってしまっている。これはバッファオーバーフローを起こしてしまっていることを表す。
詳細 仮引数が ... から va_list に変わったことを除き、snprintf関数と同等である。
変換指定の詳細については、printf関数を参照。
変換指定を行い生成された文字列のうち、引数n で指定した文字数 - 1 文字までが格納され、末尾に '\0' が付加される。変換後の文字列の長さが、格納先の配列の大きさを超えているとバッファオーバーフローが起きてしまう。
引数 n が 0 の場合、'\0' も含めて、何も書き込まれない。この場合、引数 s はヌルポインタであっても構わない。
注意 第3引数に渡す va_list型のオブジェクトは、事前に va_start による初期化が必要である。
va_list に、必要な個数の引数が含まれていない場合の動作は未定義。余分に存在している場合には、評価は行われるが、vsnprintf関数としては無視する。
この関数がバッファオーバーフローを防ぐ安全な関数であるかのように思われていることがあるが、そうではなく、やはりバッファオーバーフローは起こり得る。引数n に、配列の要素数以下の値を確実に指定することが必要である。バッファオーバーフローが起きていることを戻り値で確認できるものの、事後確認になってしまうので、すでにメモリは破壊されてしまっており、もはや手遅れである。プログラムの実行をただちに停止させることを試みることくらいしかできないだろう(それすらもできないかも知れないが)。
使用例
#include <stdio.h>
#include <stdarg.h>

static void warning(char* buf, size_t size, const char* str, ...);

int main(void)
{
    char buf[256] = "";
    int value = 100;

    if( value != 0 ){
        warning( buf, sizeof(buf), "value: %d\n", value );
    }

    puts( buf );

    return 0;
}

void warning(char* buf, size_t size, const char* str, ...)
{
    va_list args;

    va_start( args, str );

    sprintf( buf, "[WARNING] " );
    vsnprintf( buf, size, str, args );

    va_end( args );
}

実行結果:

value: 100
関連 命名規則が合致していないが、ワイド文字版は vswprintf関数である。vsnwprintf のような名前の標準関数は存在しない。
va_list の代わりに、... を用いたバージョンとして、snprintf関数がある。
解説章


参考リンク



更新履歴

'2018/4/20 「NULL」という表記を「ヌルポインタ」に修正。

'2018/4/19 全体的に文章を見直し修正。
「詳細」「注意」を加筆。

'2018/2/1 C言語編全体で表記を統一するため、「フォーマット指定」を「変換指定」に改めた。

'2018/1/22 新規作成。



標準ライブラリのリファレンス(名前順)のトップページへ

標準ライブラリのリファレンス(ヘッダ別)のトップページへ

C言語編のトップページへ

Programming Place Plus のトップページへ


はてなブックマーク Pocket に保存 Twitter でツイート Twitter をフォロー
Facebook でシェア Google+ で共有 LINE で送る rss1.0 取得ボタン RSS