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

先頭へ戻る

snprintf関数

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

int main(void)
{
    char str[10];
    int n;

    n = snprintf(str, sizeof(str), "%d", 12345);
    if( n < 0 ) {
        fputs("error\n", stderr);
    }
    else if( n >= sizeof(str) ){
        puts("truncated");
    }
    else{
        puts(str);
    }

    n = snprintf(str, sizeof(str), "%d", 1234567890);
    if( n < 0 ){
        fputs("error\n", stderr);
    }
    else if( n >= sizeof(str) ){
        puts("truncated");
    }
    else{
        puts(str);
    }

    return 0;
}

実行結果:

12345
truncated
関連 命名規則が合致していないが、ワイド文字版は swprintf関数である。
引数に ... ではなく、va_list を用いたバージョンとして、vsnprintf関数がある。
解説章


参考リンク



更新履歴

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

'2018/4/15 バッファオーバーフローに関する説明を大幅に追加した。

'2018/4/5 VisualStudio 2013 の対応終了。

'2018/4/2 「VisualC++」という表現を「VisualStudio」に統一。

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

'2018/1/22 新規作成。



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

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

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

Programming Place Plus のトップページへ


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