printf
printf(プリントエフ、print formatted)は、C言語の標準入出力ヘッダー (<stdio.h>)で宣言されている関数である。引数で与えられた書式付きの文字列を、環境によって設定された標準出力 (stdout) に出力する。JIS X 3010:2003においてその機能は「実引数にstdoutを実引数として付加したfprintf関数と等価とする」と規定されている (7.19.6.3)。
この関数は、第1引数に与えられた文字列を出力する。C言語の他の単純な入出力関数に比べ、比較的複雑な構造を持っており、第1引数の文字列のなかで書式を指定することで、第2引数以降の任意の数の引数を、書式に従って出力することができる。また、整数型(int型)の戻り値を持ち、出力に成功した場合には転送したバイト数、出力に失敗した場合には負数を返却する。
目次 |
形式 [編集]
#include <stdio.h> int printf(const char * restrict format, ...);
書式化文字列 [編集]
上記形式における第一引数formatは、それに続く実引数の変換方法を指定する。書式化文字列には、通常のマルチバイト文字または'%'で始まる変換指定のいずれかの指令を0個以上含む。多バイト文字が含まれ、かつ文字コードがシフトシーケンスに依存する場合には、書式化文字列は初期シフト状態で始まり、初期シフト状態で終わらなければならない。
変換指定 [編集]
変換指定は次の形式をとる。([ ]内は省略可能)
%[引数順][フラグ][最小フィールド幅][.精度][長さ修飾子]変換指定子
引数順 [編集]
引数順指定が存在するときは数値の後ろに'$'が入る。
char *fmt = "Invalid Command %1$s at line %2$d.\n"; printf(fmt, cmd, lineno);
で、cmdが hoge linenoが20だった場合、
Invalid Command hoge at line 20
と表示される。これだけならば大きな意味はないが、メッセージを翻訳した際、char *fmtに
"%2$d行目のコマンド %1$sは不正です"
が入っている状態にすることで、プログラムを変更せずに
20行目のコマンドhogeは不正です
のように自然な語順に翻訳することができる。これはCの規格ではなくPOSIXで規定されている。
フラグ [編集]
変換指定のフラグは以下の通り。
| フラグ | 意味 |
|---|---|
| - | フィールドの左寄せ |
| + | 常に符号を出力 |
| 空白 | 数値が正または 0 の場合は符号の代わりに空白を出力 |
| # | 代替形式。基数を表すプレフィックスの出力等 |
| 0 | 出力文字数が最小フィールド幅未満の場合は'0'を出力 |
長さ修飾子 [編集]
| 修飾子 | 意味 | 導入バージョン |
|---|---|---|
| hh | 実引数は char 型 | C99以降 |
| h | 実引数は short 型 | 全バージョン |
| l(エル) | 実引数は long 型または wchar_t 型または double 型 | wchar_t についてはC95以降、double についてはC99以降 |
| ll(エルエル) | 実引数は long long 型 | C99以降 |
| j | 実引数は intmax_t 型 | C99以降 |
| z | 実引数は size_t 型 | C99以降 |
| t | 実引数は ptrdiff_t 型 | C99以降 |
| L | 実引数は long double 型 | 全バージョン |
変換指定子 [編集]
| 指定子 | 意味 | 導入バージョン |
|---|---|---|
| d, i | 10進符号付き整数 | 全バージョン |
| u | 10進符号無し整数 | 全バージョン |
| o | 8進符号無し整数 | 全バージョン |
| x, X | 16進符号無し整数( X は大文字で出力) | 全バージョン |
| e, E | 指数形式浮動小数点数( E は大文字で出力) | 全バージョン |
| f, F | 小数形式浮動小数点数( F は大文字で出力) | 全バージョン |
| g, G | e または f 形式のうち適した方( G は大文字で出力) | 全バージョン |
| a, A | 16進浮動小数点( A は大文字で出力) | C99以降 |
| c | 文字 | 全バージョン |
| s | 文字列 | 全バージョン |
| p | ポインタの値 | 全バージョン |
| n | 整数変数に出力済み文字数を格納 | 全バージョン |
| % | '%'の出力 | 全バージョン |
関連する関数 [編集]
fprintf [編集]
fprintfは、引数にファイルポインタfpが追加され、標準出力の代わりにfpへ出力する変種である。
#include <stdio.h> int fprintf(FILE * restrict fp, const char * restrict format, ...);
sprintf, snprintf [編集]
sprintfとsnprintfは、引数にchar配列の要素へのポインタstrが追加されたもので、標準出力の代わりにstrへ出力する変種である。snprintfは、さらにstrに書き込んで良い文字数を指定する引数が追加されたものであるが、Cの標準規格に収録されたのはC99からである。
#include <stdio.h> int sprintf(char * restrict str, const char * restrict format, ...); int snprintf(char * restrict str, size_t size, const char * restrict format, ...);
wprintf, fwprintf, swprintf [編集]
wprintf, fwprintf, swprintfは、それぞれprintf, fprintf, snprintfに対応し、ワイド文字を使用するものである。sprintfに対応するワイド文字関数は存在しない。
#include <stdio.h> int wprintf(const wchar_t * restrict format, ...); int fwprintf(FILE * restrict fp, const wchar_t * restrict format, ...); int swprintf(wchar_t * restrict str, size_t size, const wchar_t * restrict format, ...);
va_listを引数に取るもの [編集]
ここまでに挙げたprintfとその変種に対して、可変個引数部分をva_listに変化させた種類が存在する。それぞれ、関数名の頭にvを付けた名称となっている。
#include <stdio.h> int vprintf(const char * restrict format, va_list args); int vfprintf(FILE * restrict fp, const char * restrict format, va_list args); int vsprintf(char * restrict str, const char * restrict format, va_list args); int vsnprintf(char * restrict str, size_t size, const char * restrict format, va_list args); int vwprintf(const wchar_t * restrict format, va_list args); int vfwprintf(FILE * restrict fp, const wchar_t * restrict format, va_list args); int vswprintf(wchar_t * restrict str, size_t size, const wchar_t * restrict format, va_list args);
安全性を向上させたもの [編集]
C11のAnnex K Bounds‐checking interfacesで規定された、安全性を向上させた種類が存在する。それぞれ、関数名の末尾に_sを付けた名称となっている。これらの関数は、__STDC_WANT_LIB_EXT1__を1に定義した上で対応するヘッダをインクルードすると宣言される。
#define __STDC_WANT_LIB_EXT1__ 1 #include <stdio.h> #include <wchar.h> int printf_s(const char * restrict format, ...); int fprintf_s(FILE * restrict fp, const char * restrict format, ...); int sprintf_s(char * restrict str, rsize_t size, const char * restrict format, ...); int snprintf_s(char * restrict str, rsize_t size, const char * restrict format, ...); int vprintf_s(const char * restrict format, va_list arg); int vfprintf_s(FILE * restrict fp, const char * restrict format, va_list arg); int vsprintf_s(char * restrict str, rsize_t size, const char * restrict format, va_list arg); int vsnprintf_s(char * restrict str, rsize_t size, const char * restrict format, va_list arg); int wprintf_s(const wchar_t * restrict format, ...); int fwprintf_s(FILE * restrict fp, const wchar_t * restrict format, ...); int swprintf_s(wchar_t * restrict str, rsize_t size, const wchar_t * restrict format, ...); int snwprintf_s(wchar_t * restrict str, rsize_t size, const wchar_t * restrict format, ...); int vwprintf_s(const wchar_t * restrict format, va_list arg); int vfwprintf_s(FILE * restrict fp, const wchar_t * restrict format, va_list arg); int vswprintf_s(wchar_t * restrict str, rsize_t size, const wchar_t * restrict format, va_list arg); int vsnwprintf_s(wchar_t * restrict str, rsize_t size, const wchar_t * restrict format, va_list arg);
以下のような機能が追加されている。
- FILE*や文字列の引数(%sに対応する可変長引数部分の引数も含む)に対するNULLポインタチェック
- %n書式の禁止
コード例 [編集]
#include <stdio.h> int main(void) { int a = 1234; printf("%d %o %x\n", a, a, a); printf("%s %c\n", "abc", 'x'); return 0; }
上記のコードをコンパイルし実行すると、次の出力が得られる。
1234 2322 4d2 abc x
脆弱性 [編集]
「書式文字列攻撃」を参照
一般に、書式文字列を外部や利用者から自由に指定できる状態とすることはセキュリティホールの温床となるため望ましくない。特に%n書式を用いたものが有名である[1]。
他言語 [編集]
C言語から派生したC++やD言語はもとより、PHP[2]、Ruby[3]、Perlなど他の言語でもprintfが実装されている。また、オブジェクト指向の言語の中には、C++でのBoost::format[4]、Ruby[5]、Pythonなど演算子としてsprintfを実行できるものも存在する。
脚注 [編集]
- ^ “第10章 著名な脆弱性対策 フォーマット文字列攻撃対策”. IPA ISEC セキュア・プログラミング講座:C/C++言語編. 独立行政法人 情報処理推進機構. 2012年7月3日閲覧。
- ^ “PHP: printf”. PHPマニュアル (2013年3月22日). 2013年3月28日閲覧。
- ^ “Kernel.#printf”. Ruby1.9.3リファレンスマニュアル. 2013年3月28日閲覧。
- ^ “The Boost Format Library” (2006年12月2日). 2013年3月28日閲覧。
- ^ “Instance method String#%”. Ruby1.9.3リファレンスマニュアル. 2013年3月28日閲覧。
参考文献 [編集]
関連項目 [編集]
外部リンク [編集]
- UNIX コマンド
- 標準 C ライブラリ
- printf(3) JM Project
- printf(3C) man page (Solaris 10 Reference Manual)
- printf(3S) man page(HP-UX リファレンス)
|
||||||||||||||||||||||||||