PRINTF(3) | FreeBSD Library Functions Manual | PRINTF(3) |
名称
printf, fprintf, sprintf, snprintf, asprintf, dprintf, vprintf, vfprintf, vsprintf, vsnprintf, vasprintf, vdprintf — フォーマットした (書式) 出力変換ライブラリ
Standard C Library (libc, -lc)書式
#define _WITH_DPRINTF#include < stdio.h>
int
printf( const char * restrict format, ...);
int
fprintf( FILE * restrict stream, const char * restrict format, ...);
int
sprintf( char * restrict str, const char * restrict format, ...);
int
snprintf( char * restrict str, size_t size, const char * restrict format, ...);
int
asprintf( char **ret, const char *format, ...);
int
dprintf( int fd, const char * restrict format, ...);
#include < stdarg.h>
int
vprintf( const char * restrict format, va_list ap);
int
vfprintf( FILE * restrict stream, const char * restrict format, va_list ap);
int
vsprintf( char * restrict str, const char * restrict format, va_list ap);
int
vsnprintf( char * restrict str, size_t size, const char * restrict format, va_list ap);
int
vasprintf( char **ret, const char *format, va_list ap);
int
vdprintf( int fd, const char * restrict format, va_list ap);
解説
printf() 関数ファミリは、下記に説明するように format にしたがって出力を生成します。 printf() と vprintf() 関数は、標準出力ストリーム stdout に出力を書き込みます。 fprintf() と vfprintf() は、与えられた出力ストリーム stream に出力を書き込みます。 dprintf() と vdprintf() は、与えられたファイル記述子に出力を書き込みます。 sprintf(), snprintf(), vsprintf() と vsnprintf() は、文字列 str に出力を書き込みます。そして asprintf() と vasprintf() は、 malloc(3) で新しい文字列を動的に割り付けます。これらの関数は、後に続く引数 (または stdarg(3) の可変長引数機能によってアクセスできる引数) が出力のためにどのように変換するかを指定する、 format 文字列の制御に従って出力を書き込みます。
asprintf() と vasprintf() 関数は、書式化された文字列を保存するために十分大きなバッファへのポインタとなるように、 *ret を設定します。このポインタは、もはや必要でなくなったときに、割り付けられた記憶域を解放するために free(3) に渡されるべきです。十分な空間を割り付けることができないなら、 asprintf() と vasprintf() は、-1 を返し、 NULL ポインタとなるように ret を設定します。
snprintf() と vsnprintf() 関数は、出力文字列 (そして size 番目の文字は、終端の‘ \0
’になります) に印刷された多くても size-1 文字を書き込みます。返り値が size 引数以上であるなら、文字列は、短かすぎ、印刷された文字の一部は、破棄されます。出力は、 size が 0 でないなら、常にヌル文字で終了します。
sprintf() と vsprintf() 関数は、事実上 INT_MAX + 1 の size であると仮定します。
フォーマット (書式) 文字列は、0 以上の指令から構成されています: 出力ストリームに変更されずにコピーされる、通常文字 ( % 以外)。そして、それぞれの変換指定は、0 以上の後続の引数を取って来る結果となります。各変換指定は、 % 文字で導入されます。引数は、(タイプ促進の後に) 変換指示子で適切に対応しなければなりません。 % の後は、次のシーケンスで現れます。
- $ が続く 10 進数文字列から成り、次にアクセスする引数を指定するオプションフィールド。このフィールドが提供されないなら、最後にアクセスされた引数に続く引数が使用されます。引数は 1 から始まる番号が付けられます。書式文字列中でアクセスされない引数がアクセスされる引数に組み入れられている場合、結果は、不定になります。
- 0 以上の次のフラグ:
- ‘ #’
-
値は“代替形式”に変換されるべきです。
c,
d,
i,
n,
p,
s および
u 変換について、このオプションは、効果がありません。
o 変換について、数値の精度は、出力文字列の最初の文字を 0 に強制するために増加させられます。
x と
X 変換について、0 以外の結果の前に文字列‘
0x
’ (または X 変換のためは‘0X
’) が付きます。 a, A, e, E, f, F, g および G 変換について、数字がそれに続かなくても、結果は、常に小数点が含まれます (通常は、数字が続く場合のみ、それらの変換の結果に小数点が現れます)。 g および G 変換について、後続する 0 は、そうでなければ (0 が後続するように) 結果から取り除かれません。 - ‘ 0’ (ゼロ)
- 0 パディング。 n 変換を除くすべての変換について、変換された値は、空白ではなく 0 で左に詰められます。精度が数値変換 ( d, i, o, u, i, x および X) で与えられる場合、 0 フラグは、無視されます。
- ‘ -’
- 負のフィールド幅のフラグ。変換された値は、フィールド境界で左に揃えられます。 n 変換を除いて、変換された値は、空白か 0 の左でなく、右に空白が埋められます。 - と 0 を両方が与えられる場合は 0 を無効にします。
- ‘ ’ (空白)
- 空白は、符号付き変換 ( a, A, d, e, E, f, F, g, G または i) によって生成される正の数値の前に残されるべきです。
- ‘ +’
- 符号は、符号付き変換によって生成される数値の前に常に置かれなければなりません。 + と空白が両方とも使用される場合は、空白を無効にします。
- ‘'’ (アポストロフィ)
- 10 進変換 ( d, u または i) か浮動小数点変換 ( f または F) の整数部 (指数部) は、 localeconv(3) によって返された非通貨のセパレータ (分離記号) を使用することで千単位でグループ化され、分離されるべきです。
- 最低フィールド幅を指定するオプションの 10 進数文字列。変換された値がフィールドの幅より少ない文字数の場合は、フィールドの幅を調整するために左に (左揃えフラグが指定された場合は、右に) 空白が埋められます。
- オプションの数字文字列が続くピリオド . の形式のオプションの精度。数字文字列を省略した場合、精度は、0 になります。 d, i, o, u, x および X 変換のために現れる最低の桁の数、 a, A, e, E, f, および F 変換のために小数点の後に現れるための桁の数、 g および G 変換のために有効な桁の最大数、 s 変換のための文字列から印刷される最大の文字の数が与えられます。
- 引数のサイズを指定する、オプションの長さ修飾子です。次の長さ修飾子は、 d, i, n, o, u, x または X 変換で有効です:
修飾子 d, i o, u, x, X n hh signed char unsigned char signed char * h short unsigned short short * l (エル) long unsigned long long * ll (エルエル) long long unsigned long long long long * j intmax_t uintmax_t intmax_t * t ptrdiff_t (注参照) ptrdiff_t * z (注参照) size_t (注参照) q (非推奨) quad_t u_quad_t quad_t * 注: t 修飾子は、 o, u, x または X 変換に適用されるとき、引数がサイズで unsigned タイプと ptrdiff_t が同等であることを示します。 z 修飾子は、 d または i 変換に適用されるとき、引数がサイズで signed タイプと size_t が同等であることを示します。同様に、 n 変換に適用されるとき、それは、引数がサイズで signed タイプへのポインタと size_t が同等であることを示します。
次の長さ修飾子 a, A, e, E, f, F, g または G 変換で有効です:
修飾子 a, A, e, E, f, F, g, G l (エル) double (無視されます、それ以外は、同じ振る舞い) L long double 次の長さ修飾子 c または s 変換で有効です:
修飾子 c s l (エル) wint_t wchar_t * - 適用される変換の型を指定する文字。
フィールド幅か精度、またはその両方は、アスタリスク‘ *
’、または数字文字列の代わりに 1 つ以上の 10 進数と‘ $
’が続くアスタリスクで指示できます。この場合、 int 引数は、フィールド幅か精度を供給します。負のフィールド幅は、正のフィールド幅が続く左揃えフラグとして扱われます。負の精度は、まるで欠落しているかのように扱われます。 1 つのフォーマット (書式) 指令が位置引数 ( nn$
) と位置以外の引数が混在している場合、結果は、未定義になります。
変換指示子とその意味は、次の通りです:
- diouxX
-
int (または適切な可変) 引数が、符号付き 10 進 (
d と
i)、符号なし 8 進 (
o)、符号なし 10 進 (
u)、符号なし 16 進 (
x と
X) 記法に変換されます。文字“
abcdef
”は、 x 変換のために使われます。文字“ABCDEF
”は、 X 変換のために使われます。精度は、もしあれば、現れるべき桁の最低数を与えます。変換された値が少ない桁を要求する場合は、左に 0 が埋められます。 - DOU
- long int 引数は、それぞれの形式が ld, lo および lu であるかのように符号付き 10 進、符号なし 8 進、符号なし 10 進に変換されます。これらの変換文字は、非推奨であり、最終的には、消滅するでしょう。
- eE
-
double 引数が丸められ、[
-]
d
.
ddde±
dd のスタイルに変換されます。ここで、小数点文字の前は、1 桁で、後の桁の数は、精度と等しくなります。精度が欠けている場合は、6 が取られます。精度が 0 である場合、小数点文字は、現れません。 E 変換では、指数を導入するために、文字 (‘e
’ではなく) ‘E
’が使われます。指数は、少なくとも 2 桁が常に含まれます。値が 0 である場合、指数は、00 になります。a, A, e, E, f, F, g および G 変換において、正と負の無限は、小文字の変換文字を使用するとき、それぞれ
inf
と-inf
で表現され、大文字の変換文字を使用するとき、それぞれINF
と-INF
で表現されます。同様に、NaN は、小文字の変換を使用するとき、nan
で、大文字の変換を使用するとき、NAN
で表現されます。 - fF
-
double 引数が丸められ、[
-]
ddd
.
ddd のスタイルで 10 進記法に変換されます。ここで、小数点文字の後の桁の数は、精度指定に等しくなります。精度が欠けている場合は、6 が取られます。精度が明白に 0 である場合、小数点文字は、現れません。小数点が現れる場合は、それの前に少なくとも 1 桁が現れます。 - gG
- double 引数は、スタイル f か e (あるいは G 変換のためには、 F または E) で変換されます。精度は、有効桁数を指定します。精度が欠けている場合は、6 桁が与えられます。精度が 0 である場合は、1 として扱われます。変換後の指数が-4 より小さいか精度以上である場合は、スタイル e が使用されます。後続する 0 は、結果の小数部から取り除かれます。小数点は、少なくとも 1 つ桁が続く場合のみ現れます。
- aA
-
double 引数は、丸められ、スタイル[
-]
0x
h.
hhhp[ ±] d で 16 進記法へ変換されます。ここで、16 進ポイント文字の後の桁数は、精度指定と同じです。精度が欠けているなら、浮動小数点の数を正確に表現するために十分に取られます、そして丸めは起こりません。精度が 0 であるなら、16 進ポイント文字は、現れません。 p は、リテラル文字‘p
’で、指数は、2 の指数で表現される 10 進数があとに続いて正と負のサインから成ります。 A 変換は、16 進数桁を表すために接頭辞 (“0x
”よりむしろ) “0X
”、文字 (“abcdef
”よりむしろ) “ABCDEF
”および仮数と指数を分離するために (‘p
’よりむしろ) 文字‘P
’を使用します。この 16 進形式で浮動小数点数を表現する複数の有効な方法があるかもしれないことに注意してください。例えば、
0x1.92p+1
,0x3.24p+0
,0x6.48p-1
と0xc.9p-2
は、すべて同等です。 FreeBSD 8.0 以降は、16 進数点の前の桁として‘1
’を使用して有限の非 0 番号を常に印刷します。 0 は、常に (適切であるなら、‘-
’によって先行され) 0 の仮数と+0
の指数で表現されます。 - C
- l (エル) 修飾子がある c として取り扱われます。
- c
-
int 引数は、
unsigned char に変換され、結果の文字が書き込まれます。
l (エル) 修飾子が使用されているなら、 wint_t 引数は、 wchar_t に変換されるべきで、単一のワイド文字で表される (潜在的にマルチバイトの) シーケンスは、いくらかのシフトシーケンスを含んで書き込まれます。シフトシーケンスが使用されているなら、シフト状態は、文字の後でまた元の状態に復元されます。
- S
- l (エル) 修飾子がある s として取り扱われます。
- s
-
char * 引数が、文字型の配列を指すポインタ (文字列へのポインタ) が期待されます。配列の文字は、終端の
ヌル文字 まで (しかし含まずに) 書き込まれます。精度が指定されている場合、指定された数以上は書き込まれません。精度が与えられる場合、ヌル文字は、存在する必要はありません。精度が指定されていない場合、または精度が配列のサイズより大きい場合、配列は、終端の
ヌル文字 を含まなければなりません。
l (エル) 修飾子が使用されているなら、 wchar_t * 引数は、ワイド文字 (ワイド文字列へのポインタ) の配列へのポインタであると期待されます。文字列中のそれぞれのワイド文字において、ワイド文字で表される (潜在的にマルチバイトの) シーケンスは、いくらかのシフトシーケンスを含んで書き込まれます。シフトシーケンスが使用されているなら、シフト状態は、文字列の後でまた元の状態に復元されます。配列からのワイド文字は、終端のワイド ヌル 文字 (しかし、含めない) まで書き込まれます。精度が指定されるなら、わずかの指定されたバイトの数が (シフトシーケンスを含んで) 書き込まれます。 (ワイド文字の片方のみなど) 部分的な文字は、決して書き込まれません。精度が与えられるなら、ヌル文字は、存在する必要はありません。精度が指定されないか、または文字列のマルチバイト表現を示す必要があるバイト数より大きいなら、配列は、終端のワイド ヌル 文字を含まなければなりません。
- p
-
void * ポインタ引数は、16 進で (あたかも‘
%#x
’か‘%#lx
’によるかのように) 印刷されます。 - n
- これまでに書き込まれた文字数は、 int * (または可変) ポインタ引数で示された整数に格納されます。引数は、変換されません。
- %
-
‘
%
’が書き込まれます。引数は、変換されません。完全な変換指示は、‘%%
’です。
小数点文字は、プログラムのロケール (カテゴリ LC_NUMERIC) で定義されます。
フィールド幅が存在しないか小さい場合でも、決して数値フィールドは、切り捨てられません。変換の結果がフィールド幅より大きい場合、フィールドは、変換結果を含むために拡張されます。
戻り値
size の制限がなかったなら、印刷された文字の数 (最後の‘\0
’は、含みません) を返す、
snprintf() と
vsnprintf() を除いて、これらの関数は、印刷された文字の数 (文字列への出力を終了するために使用される、後続する‘
\0
’を含まない) を返します。これらの関数は、エラーが生じたなら、負の値を返します。
例
weekday と month が文字列へのポインタである場合に“Sunday, July 3, 10:02
”という形式で日付と時刻を出力する場合。
#include <stdio.h> fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
pi を小数第 5 位まで出力する場合。
#include <math.h> #include <stdio.h> fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
128 バイトの文字列を割り付け、そこに印刷する場合。
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> char *newfmt(const char *fmt, ...) { char *p; va_list ap; if ((p = malloc(128)) == NULL) return (NULL); va_start(ap, fmt); (void) vsnprintf(p, 128, fmt, ap); va_end(ap); return (p); }
互換性
dprintf() 関数が IEEE Std 1003.1 (“POSIX.1”) で導入される前に、多くのアプリケーションの作者は、 dprintf という名前を使用していたので、プロトタイプは、互換性の問題を避けるためにデフォルトで提供されません。ここに説明された dprintf() 関数を使用したいアプリケーションは、マクロ _POSIX_C_SOURCE を値 200809 以上と定義することによって、厳格な IEEE Std 1003.1-2008 (“POSIX.1”) 環境変数を要求するか、または < stdio.h> をインクルードする前にマクロ _WITH_DPRINTF を定義するべきです。 GNU libc との互換性のために、 < stdio.h> をインクルードする前に _BSD_SOURCE または _GNU_SOURCE のいずれかを定義しても、 dprintf() は、利用可能となります。変換形式 %D, %O と %U は、標準ではなく、後方互換性のためだけに提供されています。 %p 形式を ( 0 フラグまたは精度を指定するかのいずれかで) 0 をパディングする効果と %n と %p 変換で # フラグの良性の効果 (つまりなし) は、 %Ld のような他の無意味な組み合わせと同様に標準ではありません。そのような組み合わせは避けられるべきです。
エラー
write(2) システムコールのためにドキュメント化されたエラーに加えて、 printf() ファミリ関数は、次の場合に失敗します:- [ EILSEQ]
- 無効のワイド文字コードに遭遇しました。
- [ ENOMEM]
- 利用可能な記憶域空間が不足しています。
規格
下記の バグ セッションで注意された警告を前提として、 fprintf(), printf(), sprintf(), vprintf(), vfprintf() と vsprintf() 関数は、 ANSI X3.159-1989 (“ANSI C89”) と ISO/IEC 9899:1999 (“ISO C99”) に適合しています。同じ条件で、 snprintf() と vsnprintf() 関数は、 ISO/IEC 9899:1999 (“ISO C99”) に適合しています、一方 dprintf() と vdprintf() は、 IEEE Std 1003.1-2008 (“POSIX.1”) に適合しています。歴史
関数 asprintf() と vasprintf() は、 GNU C ライブラリではじめて登場しました。これらは、 FreeBSD 2.2 で <peter@FreeBSD.org>によって実装されましたが、その後 <Todd.Miller@courtesan.com>によって OpenBSD 2.3 から異なった実装で置き換えられました。 dprintf() と vdprintf() 関数は、 FreeBSD 8.0 で追加されました。バグ
printf 関数ファミリは、 format 引数で正しくマルチバイト文字を取り扱いません。セキュリティの考察
sprintf() と vsprintf() 関数は、悪意があるユーザがバッファオーバフロー攻撃で実行プログラムの機能性を任意に変更することを可能にする方法で容易に悪用されます。 sprintf() と vsprintf() は、無限に長い文字列を仮定するので、呼び出し側は、実際の空間をオーバフローしないように注意しなければなりません。保証することはしばしば困難です。安全のために、プログラマは、 snprintf() インタフェースを代わりに使用するべきです。例えば:
void foo(const char *arbitrary_string, const char *and_another) { char onstack[8]; #ifdef BAD /* * この最初の sprintf は悪い振る舞いです。sprintf を使用しなこと! */ sprintf(onstack, "%s, %s", arbitrary_string, and_another); #else /* * 次の 2 つの行は、snprintf() のより良い使用例です。 * */ snprintf(onstack, sizeof(onstack), "%s, %s", arbitrary_string, and_another); #endif }
printf() と sprintf() 関数ファミリは、“スタックの上に残された”潜在的な機密のデータを印刷するのを引き起こすか、または無効のポインタの修飾参照によってメモリフォルトかバスエラーを発生させるのを引き起こすかのいずれかによって悪意があるユーザが任意に実行プログラムの機能性を変更する方法で容易に悪用されます。
潜在的に慎重に選択されたアドレスに任意のデータを書き込むために %n を使用することができます。したがって、プログラマは、 format 引数として、攻撃者が可能性のあるセキュリティホールの原因となる、利用者のスタックを台なしにする文字列でフォーマット (形式) 記述子を置くことができるような、信頼されていない文字列を決して渡さないように強く勧められます。結果として作成される文字列にまだ printf() によって後の挿入のためにユーザによって供給された変換指示子を含んでいるとき、文字列が snprintf() のような関数を使用することで構築されたとしても、このホールは、当てはまります。
常に適切で安全な慣用法を使用してください:
snprintf(buffer, sizeof(buffer), "%s", string);
December 2, 2009 | FreeBSD |