other versions
other sections
PRINTF(3) | Linux Programmer's Manual | PRINTF(3) |
名前¶
printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 指定された書式に変換して出力を行う書式¶
#include <stdio.h> int printf(const char *format, ...);glibc 向けの機能検査マクロの要件 ( feature_test_macros(7) 参照):
snprintf(), vsnprintf():
_BSD_SOURCE || _XOPEN_SOURCE >= 500 ||
_ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L;
または cc -std=c99
説明¶
printf() 関数グループは、以下で述べるように、 format に従って出力を生成するものである。 printf() と vprintf() は出力を stdout (標準出力ストリーム) に書き出す。 fprintf() と vfprintf() は出力を指定された出力 stream に書き出す。 sprintf(), snprintf(), vsprintf(), vsnprintf() は出力を文字列 str に書き込む。 snprintf() と vsnprintf() は最大で size バイトを str に書き込む ( size には文字列を終端するヌルバイト ('\0') もを含まれる)。 vprintf(), vfprintf(), vsprintf(), vsnprintf() の各関数はそれぞれ printf(), fprintf(), sprintf(), snprintf(), の各関数と等価であり、可変数引き数の代わりに va_list を引き数として呼び出される点だけが異なる。 これらの関数では va_end マクロは呼び出されない。 これらの関数は va_arg を呼び出すので、呼び出し後の ap の値は未定義である。 stdarg(3) を参照のこと。 これらの 8 つの関数は format 文字列の制御に従って出力を書き出す。 format 文字列は、これに続く引き数 (または stdarg(3) の可変長引き数機構を使ってアクセスできる引き数) をどのように変換して出力するかを指定する。 C99 と POSIX.1-2001 では、 sprintf(), snprintf(), vsprintf(), vsnprintf() の呼び出しで、範囲が重複するオブジェクト間でコピーが発生する場合の 結果は不定であると規定されている (例えば、出力先の文字列と入力された 引き数の一つが同じバッファを参照している場合などである)。 「注意」の節を参照。Return Values¶
成功時には、上記の関数は書き込まれた文字数を返す (文字列の最後を示すために使用するヌルバイトは数に含まれない)。 snprintf() と vsnprintf() は、 size バイトを越える文字数を書き込まない ( size には文字列を終端するヌルバイト ('\0') も含まれる)。 この制限によって出力が切り詰められた場合には、 もし十分なスペースがあれば書き込まれたであろう文字の個数 (文字列を終端するヌルバイトを除く) を返す。 従って、返り値が size 以上だった場合、出力が切り詰められたことを意味する (後述の注意も参照のこと)。 エラーが発生した場合は、負の数を返す。フォーマット文字列のフォーマット¶
フォーマット文字列は文字の列で、 (もしあるなら) 初期シフト状態で始まり、初期シフト状態で終わる。 フォーマット用の文字列は 0 個以上の命令 (directives) によって構成される。 命令には、通常文字と変換指定 (conversion specifications) がある。 通常文字は % 以外の文字で、出力ストリームにそのままコピーされる。 変換指定は、それぞれが 0 個以上の引き数を取る。 各変換指定は文字 % で始まり、 変換指定子 (conversion specifier) で終わる。 % と変換指定子の間には、0 個以上の フラグ 、 最小 フィールド幅 、 精度 、 長さ修飾子 を (この順序で) 置くことができる。 引き数は (型の格上げの後は) 変換指定子が表す型と正確に対応しなければならない。 デフォルトでは、'*' や変換指定子が出てくる毎に次の引き数を要求され、 引き数は指定された順序で使用されていく (指定された引き数の個数が不十分ならエラーとなる)。 また、引き数が必要な箇所で '%' の代わりに "%m$"、 '*'の代わりに "*m$" と書くことで、 明示的にどの引き数を使用するかを指定することもできる。 ここで 10進の整数 m は希望の引き数の引き数リストでの位置を示す (最初の引き数の番号が 1 である)。 従って、printf("%*d", width, num);
と
printf("%2$*1$d", width, num);
は等価である。 二番目の書き方では同じ引き数を繰り返し参照することができる。 C99 標準には、 Single UNIX Specification 由来の '$' を使った書き方は含まれていない。 '$' を使ったスタイルを使うと、引き数を取る変換及び幅と精度の引き数を 全てこのスタイルで指定しなければならないが、 引き数を消費しない "%%" フォーマットと混ざっているかもしれない。 '$' で指定される引き数の番号に空きがあってはならない。 例えば、もし引き数 1 と 3 が指定されると、引き数 2 もフォーマット文字列のどこかで 指定されなければならない。 数値変換には小数点や 1000 単位の区切り文字を使うものもある。 実際にどの文字を使うかはロケールの LC_NUMERIC による。 POSIX ロケールでは小数点に '.' を用い、 区切り文字は使わない。 従って、
printf("%'.2f", 1234567.89);
は、 POSIX ロケールでは "1234567.89" 、 nl_NL ロケールでは "1234567,89"、 da_DK ロケールでは "1.234.567,89" となる。
フラグ文字¶
% 文字の後ろには 0 個以上のフラグ文字が続く。- #
- 値は「別の形式」に変換される。 o 変換の場合、(先頭文字が 0 になっていない場合に先頭に 0 を追加することで) 出力文字列の最初の文字を 0 にする。 x と X 変換の場合、数値が 0 でないときには文字列 "0x" ( X 変換の場合には "0X") が前に付与される。 a, A, e, E, f, F, g, G 変換では、 小数点に続く数字がなくても、 出力には常に小数点が含まれる (通常は、小数点の後に数字が続く場合にのみ、 小数点が表示される)。 g と G 変換の場合、他の変換とは異なり、末尾のゼロが変換結果から削除されない。 その他の変換では、結果は未定義である。
- 0
- 値をゼロで埋める。 d, i, o, u, x, X, a, A, e, E, f, F, g, G 変換では、変換した値の左側を空白文字の代わりにゼロで埋める。 0 と - が両方とも指定された場合は、 0 フラグは無視される。 精度が数値変換 ( d, i, o, u, x, X) と同時に指定された場合には、 0 フラグは無視される。 その他の変換では、動作は未定義である。
- -
- 変換値をフィールド境界で左揃えにする (デフォルトは右揃えである)。 n 変換以外では、変換された値は 左側ではなく右側を空白文字やゼロで埋められる。 - と 0 の両方が指定された場合には、 - が優先される。
- ' '
- (1個の半角スペース) 符号付き変換で生成された正の数字の前に空白 (または空文字列) が置かれる。
- +
- 符号付き変換によって出力される数字の前に、常に符号 (+ か -) が置かれる。 デフォルトでは、符号は負の数字の場合のみ付与される。 + と半角スペースの 両方が使われている場合には、 + が優先される。
- '
- 10進数変換 (i, d, u, f, F, g, G) において、ロケール情報に指定があれば 1000 単位の区切り文字を出力する。 gcc(1) の多くのバージョンは、このオプションを解釈することができず、 警告を出力することに注意せよ。 %'F は SUSv2 には含まれていない。
- I
- 10進整数変換 (i, d, u) において、ロケールの代替出力数字があれば、それを用いて出力する。 例えば、 glibc 2.2.3 以降では、ペルシア ("fa_IR") ロケールで アラビア数字 (Arabic-Indic digits) を出力できる。
フィールド幅¶
最小のフィールド幅を指定する 10進数の数値文字列 (文字列の最初の文字は ゼロ以外)。本項目はオプションである。 変換された値の文字数がフィールド長よりも少ない場合、 フィールドの左側をスペースで埋める (左揃えのフラグがある場合は右側を埋める)。 10進数の文字列の代わりに "*" や "*m$" ( m は 10進整数) を書くこともできる。 "*" と "*m$" はそれぞれ、次の引き数と m 番目の引き数をフィールド幅として 使うことを指定する (これらの引き数は int 型でなければならない)。 フィールド幅に負の数が指定された場合は、 '-' フラグと正の数のフィールド幅として扱われる。 フィールド幅が小さかったり指定がなかったりしても、フィールドが切り詰められる ことはない。もし変換結果がフィールド幅よりも広かった場合、 フィールドは変換結果が入る幅に広げられる。精度¶
オプションである精度は、ピリオド ('.') とそれに続く10進数という 形式で指定する (10進数はオプション) 。 10進数の文字列の代わりに "*" や "*m$" (m は 10 進整数)を書くこともできる。 "*" と "*m$" はそれぞれ、次の引き数と m 番目の引き数を精度として 使うことを指定する (これらの引き数は int 型でなければならない)。 精度として '.' だけが指定された場合、 精度はゼロとみなされる。 精度が負の数だった場合、 精度は指定されなかったものとみなされる。 d, i, o, u, x, X 変換では、表示される最小の桁数を指定する。 a, A, e, E, f, F 変換では、小数点以下に表示される数字の桁数を指定する。 g と G 変換では、有効数字の最大桁数を指定する。 s と S 変換では、文字列から出力される最大文字数を指定する。長さ修飾子¶
「整数変換」とは、 d, i, o, u, x, X 変換のことである。- hh
- 整数変換に対応する引き数が signed char か unsigned char で、 n 変換に対応する引き数が signed char へのポインタであることを示す。
- h
- 整数変換に対応する引き数が short int か unsigned short int で、 n 変換に対応する引き数が short int へのポインタであることを示す。
- l
- 各変換に対応する引き数が、 整数変換では long intか unsigned long int、 n 変換では long long int へのポインタ、 c 変換では wint_t、 s 変換では wchar_t へのポインタであることを示す。
- ll (エルエル)
- 整数変換に対応する引き数が long long int か unsigned long long int で、 n 変換に対応する引き数が long int へのポインタであることを示す。
- L
- a, A, e, E, f, F, g, G 変換に対応する引き数が long double であることを示す。 (C99 では %LF を使うことを認めているが、SUSv2 では認められていない。)
- q
- ("quad"。 4.4BSD と Linux libc5 のみ有効。使ってはならない。) ll と同じ意味である。
- j
- 整数変換に対応する引き数が intmax_t か uintmax_t であることを示す。
- z
- 整数変換に対応する引き数が size_t か ssize_t であることを示す。 (Linux libc5 では、これを指定するのに Z を用いる。使ってはならない。)
- t
- 整数変換に対応する引き数が ptrdiff_t であることを示す。
変換指定子¶
適用される変換の型を指定する文字。 変換指定子とその意味は以下の通りである。- d, i
- int 引き数を符号付き 10 進表記に変換する。 精度指定があれば、精度で指定した桁数は必ず出力される。変換後の値が 指定された桁数に足りない場合は、左側が 0 で埋められる。 デフォルトの精度は 1 である。 0 を表示しようとした時に、明示的に精度として 0 が指定されていると、 出力は空文字列となる。
- o, u, x, X
- unsigned int 引き数を、 符号なし8進数 ( o), 符号なし10進数 ( u), 符号なし16進数 ( x と X) に変換する。 x 変換では abcdef が使用され、 X 変換では ABCDEF が使用される。 精度指定があれば、精度で指定した桁数は必ず出力される。変換後の値が 指定された桁数に足りない場合は、左側が 0 で埋められる。
- e, E
- double 引き数を丸めて [-]d .ddde±dd の形に変換する。 小数点の前には一桁の数字があり、小数点以下の桁数は精度で指定された桁数 になる。精度は指定されなかった場合 6 とみなされる。 精度が 0 の場合には、 小数点以下は表示されない。 E 変換では、指数を表現するときに ( e で はなく) E が使われる。指数部分は少なくとも 2桁表示される。つまり、 指数の値が 0 の場合には、00 と表示される。
- f, F
- double 引き数を丸めて
[-]ddd .ddd
の形の10進表現に変換する。
小数点の後の桁数は、精度で指定された値となる。
精度が指定されていない場合には
6 として扱われる。
精度として明示的に 0
が指定されたときには、小数点以下は表示されない。
小数点を表示する際には、小数点の前に少なくとも一桁は数字が表示される。
(SUSv2 では、 F
は規定されておらず、無限や
NaN
に関する文字列表現を
行ってもよいことになっている。
C99 標準では、 f 変換では、無限は "[-]inf" か "[-]infinity" と表示し、 NaN は文字列の先頭に `nan' をつけて表示するように規定されている。 F 変換の場合は "[-]INF", "[-]INFINITY", "NAN*" と表示される。)
- g, G
- double 引き数を f か e ( G 変換の場合は F か E) の形式に変換する。 精度は表示する桁数を指定する。 精度が指定されない場合は、6桁とみなされる。 精度が 0 の場合は、1桁とみなされる。 変換される値の指数が、 -4 より小さいか、精度以上の場合に、 e 形式が使用される。 変換された結果の小数部分の末尾の 0 は削除される。小数点が表示されるのは、 小数点以下に数字が少なくとも一つある場合にだけである。
- a, A
- (C99 にはあるが SUSv2 にはない) a 変換では、 double 引き数を (abcdef の文字を使って) [-] 0xh.hhhhp± 形式の 16 進表記に変換する。 A 変換では、前置文字列 0X, 文字 ABCDEF, 指数文字 P を用いる。 小数点の前には 1 桁の 16 進数が置かれ、小数点の後ろの桁数は 精度で指定 された値となる。デフォルトの精度は、その値が 2 進数で正確に表現できる 場合には、その値を正確に表現できる桁数となる。それ以外の場合は、 double 型の値を区別するのに十分な大きさとなる。 小数点の前の数字は、 正規化されていない数の場合はいくつになるか分からない。 正規化された数の 場合は、 0 以外の値になるが、いくつになるかは分からない。
- c
- l 修飾子がなければ、 int 引き数を unsigned char に変換して、その結果に対応する文字を出力する。 l 修飾子があれば、 wint_t (ワイド文字) 引き数を、 wcrtomb(3) 関数を初期シフト状態で呼び出してマルチバイト文字列に変換し、 変換されたマルチバイト文字列を出力する。
- s
- l 修飾子がない場合、 引き数は const char * 型で文字型の配列へのポインタ (文字列へのポインタ) であることが 期待されている。配列中の文字は、終端の ヌルバイト ('\0') が出てくるまで出力される (終端文字は出力されない)。 精度が指定されていると、指定された字数以上は出力されない。 精度が指定された場合には、終端バイトが存在する必要はない。 精度が指定されていなかったり、精度の値が配列の大きさより大きい場合には、 配列は終端のヌルバイトを含んでいなければならない。 l 修飾子が指定されている場合、 引き数は const wchar_t * 型でワイド文字の配列へのポインタであることが期待されている。 配列中のワイド文字は (1文字毎に wcrtomb(3) を呼び出して) マルチバイト文字に変換される (最初のワイド文字の変換の前に wcrtomb() のシフト状態を初期状態に戻してから変換は行われる)。 マルチバイト文字への変換は、文字列を終端するヌルワイド文字が 出てくるまで行われ、終端ヌルワイド文字も含めて変換される。 結果のマルチバイト文字列は、終端のヌルバイトが出てくるまで 出力される (終端のヌルバイトは出力されない)。 精度が指定された場合、指定されたバイト数以上には出力されない。 但し、マルチバイト文字の一部分だけが出力されることはない。 精度は「バイト」数を指定するものであり、「ワイド文字」数や 「画面での位置」を指定するものではないことに注意。 精度が指定されていて、さらに出力が配列の末尾に達する前に出力バイト数が 精度の値を超える場合だけは、配列はヌルワイド文字で終端されていなくてもよい。 それ以外の場合は、必ず配列はヌルワイド文字で終端されていなければならない。
- C
- (C99 にはないが SUSv2 にはある) lc と同じ。使ってはならない。
- S
- (C99 にはないが SUSv2 にはある) ls と同じ。使ってはならない。
- p
- void * ポインタ引き数を ( %#x や %#lx のような) 16 進数で出力する。
- n
- これまでに出力された文字数を int * (または類似の型) のポインタ引き数が指す整数に保存する。 引き数の変換は行われない。
- m
- (glibc での拡張) strerror(errno) の出力を表示する。引き数は必要ない。
- %
- '%' 文字を出力する。変換される引き数は無い。 変換指定全体を書くと "%%" となる。
準拠¶
fprintf(), printf(), sprintf(), vprintf(), vfprintf(), vsprintf() 関数は、C89 と C99 に準拠している。 snprintf() と vsnprintf() は C99 に準拠している。 snprintf() の返り値を見ると、 SUSv2 と C99 標準は互いに矛盾している。 SUSv2 では、 snprintf() が size=0 で呼び出された場合、 1 未満の値を何か返り値とするように規定している。 一方 C99 では、このような場合 str を NULL とし、返り値として (通常通り) 出力バッファが十分な大きさが あった場合に出力されるであろう文字数を返す。 Linux libc4 では、 5 つの C 標準のフラグ、 長さ修飾子 h, l, L、変換 c, d, e, E, f, F, g, G, i, n, o, p, s, u, x, X が使える。 但し F は f と同義である。 また、 D, O, and U を ld, lo, and lu と同じものとして使える (これはまずい仕様で、 後に %D の対応が打ち切られた時に深刻なバグを 引き起こした)。ロケール依存の小数点、1000 区切り、 NaN と無限、 "%m$" と "*m$" は使えない。 Linux libc5 では、 5 つの C 標準のフラグと ' フラグ、ロケール、 "%m$" と "*m$" が使える。 また、長さ修飾子 h, l, L, Z, iand q が使えるが、 L と q は両方とも long double と long long int に対応している (これはバグである)。 現在では変換 F, D, O, U は認識されないが、変換文字 m が追加された。これは strerror(errno) を出力するものである。 glibc 2.0 では、変換文字 C と S が追加された。 glibc 2.1 では、長さ修飾子 hh, j, t, z と変換文字 a, A が追加された。 glibc 2.2 では、 C99 で規定された意味での変換文字 F と フラグ文字 I が追加された。注意¶
テキストを buf に追加するのに、軽率にも次のようなコードを使っているプログラムがある。sprintf(buf, "%s some further text", buf); しかしながら、標準規格では、 sprintf(), snprintf(), vsprintf(), vsnprintf() の呼び出しにおいて、コピー元とコピー先のバッファが重なっていた場合の 結果は不定である、と明記されている。 使用する gcc(1) のバージョンや指定したコンパイラのオプション次第では、 上記のような呼び出しで、期待した結果が得られ「ない」ことがある。 glibc の snprintf() と vsnprintf() の実装は、バージョン 2.1 以降は C99 標準に準拠しており、 上記の通りの動作をする。 glibc 2.0.6 までは、出力が切り詰められた場合は -1 を返す。
バグ¶
sprintf() と vsprintf() は勝手に十分に長い文字列領域があると仮定するので、呼び出し側は 実際の領域からあふれないように注意しなければならない。 しかし、これを保証することが不可能な場合が多い。 生成される文字列の長さはロケール依存であり、予測が難しいことに注意。 代わりに snprintf() と vsnprintf() (または asprintf(3) と vasprintf(3)) を使うこと。 Linux libc4.[45] には snprintf() はないが、 libbsd が提供されており、 その中には sprintf() と等価な (つまり size 引き数を無視する) snprintf() がある。 したがって、初期の libc4 で snprintf() を使うと、深刻なセキュリティ問題を引き起こすことがある。 printf(foo); のようなコードはしばしばバグを引き起こす。 なぜなら foo に % 文字が含まれてるかもしれないからである。 foo が信頼できないユーザー入力から作られている場合には、 その中に %n が含まれていることがあり、 printf() 呼び出し時にメモリへの書き込みが起こり、 セキュリティーホールを作ることになるかもしれない。例¶
Pi を 5 桁で出力する。#include <math.h> #include <stdio.h> fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
日付と時間を "Sunday, July 3, 10:02" の形式で出力する。 ( weekday と month は文字列へのポインタである)
#include <stdio.h> fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
日 - 月 - 年 の順序で表示を行う国も多い。 従って、国際版では書式で指定された順番で 引き数を表示できなければならない。
#include <stdio.h> fprintf(stdout, format, weekday, month, day, hour, min);
format はロケールに依存しており、引き数の順番を変えることもできる。 format が
"%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
であれば、 "Sonntag, 3. Juli, 10:02" という結果になる。 十分に大きな文字列領域を確保して、そこにメッセージを格納するには (glibc 2.0 と glibc 2.1 の両方で正しく動作するコード):
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * make_message(const char *fmt, ...) { int n; int size = 100; /* Guess we need no more than 100 bytes */ char *p, *np; va_list ap; p = malloc(size); if (p == NULL) return NULL; while (1) { /* Try to print in the allocated space */ va_start(ap, fmt); n = vsnprintf(p, size, fmt, ap); va_end(ap); /* Check error code */ if (n < 0) { free(p); return NULL; } /* If that worked, return the string */ if (n < size) return p; /* Else try again with more space */ size = n + 1; /* Precisely what is needed */ np = realloc(p, size); if (np == NULL) { free(p); return NULL; } else { p = np; } } }バージョン 2.0.6 より前の glibc で切り詰めが起こった場合、切り詰めは適切に処理されず、エラーとして扱われる。
関連項目¶
printf(1), asprintf(3), dprintf(3), scanf(3), setlocale(3), wcrtomb(3), wprintf(3), locale(5)この文書について¶
この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2013-12-30 | GNU |