Printf

printfは、C言語の標準ライブラリに属し、ヘッダー  で宣言されている関数である。引数で与えられた書式付きの文字列を、環境によって設定された標準出力  に出力する。その機能はJIS X 3010:2003においてprintf関数は，与えられた実引数の前にstdoutを実引数として付加したfprintf関数と等価とする。と規定されている 。

この関数は、第1引数に与えられた文字列を出力する。C言語の他の単純な入出力関数に比べ、比較的複雑な構造を持っており、第1引数の文字列のなかで書式を指定することで、第2引数以降の任意の数の引数を、書式に従って出力することができる。また、整数型の戻り値を持ち、出力に成功した場合には転送したバイト数、出力に失敗した場合には負数を返却する。

1. 形式
-----

include int printf;<WtXmlEndTag />

2. 書式化文字列
---------

上記形式における第一引数には、それに続く実引数の変換方法を指定する。書式化文字列には、通常のマルチバイト文字または%で始まる変換指定のいずれかの指令を0個以上含む。マルチバイト文字が含まれ、かつ文字コードがシフトシーケンスに依存する場合には、書式化文字列は初期シフト状態で始まり、初期シフト状態で終わらなければならない。書式指定を行う%〜それぞれを書式指定子と呼ぶ。

2.1. 変換指定
---------

変換指定は次の形式をとる。 %[引数順][フラグ][最小フィールド幅][.精度][長さ修飾子]変換指定子

2.2. 引数順 
----------------

これは標準C規格の仕様ではなく、POSIXで規定されている拡張である。

書式文字列において%の代わりに%//m//$を記述することで、続く可変長引数のうちどれを使うかを番号//m//で指定できる。 例えば、 const char* fmt = "Invalid command %1$s at line %2$d. "; const char* cmd = "hoge"; const int lineNumber = 20; printf; とした場合、 Invalid command hoge at line 20. と表示される。これだけならば大きな意味はないが、例えばメッセージを翻訳する際、 const char* fmt = "%2$d行目のコマンド %1$s は不正です。 "; というように書式文字列だけをローカライズすることで、可変長引数の指定順を変更せずに、 20行目のコマンド hoge は不正です。 という自然な語順の出力を得ることができる。

2.3. フラグ
--------

変換指定のフラグは以下の通り。



2.4. 長さ修飾子
----------



2.5. 変換指定子
----------



3. 関連する関数
---------

3.1. fprintf
------------

fprintfは、引数にファイルポインタfpが追加され、標準出力の代わりにfpへ出力する変種である。

include int fprintf;<WtXmlEndTag />

3.2. sprintf, snprintf
----------------------

sprintfとsnprintfは、引数にchar配列の要素へのポインタstrが追加されたもので、標準出力の代わりにstrへ出力する変種である。snprintfは、さらにstrに書き込んで良い文字数を指定する引数が追加されたものであるが、Cの標準規格に収録されたのはC99からである。

include int sprintf; int snprintf;<WtXmlEndTag />

3.3. wprintf, fwprintf, swprintf
--------------------------------

wprintf, fwprintf, swprintfは、それぞれprintf, fprintf, snprintfに対応し、ワイド文字を使用するものである。sprintfに対応するワイド文字関数は存在しない。

include int wprintf; int fwprintf; int swprintf;<WtXmlEndTag />

3.4. va_listを引数に取るもの
--------------------

ここまでに挙げたprintfとその変種に対して、可変個引数部分をva_listに変化させた種類が存在する。それぞれ、関数名の頭にvを付けた名称となっている。

include int vprintf; int vfprintf; int vsprintf; int vsnprintf; int vwprintf; int vfwprintf; int vswprintf;<WtXmlEndTag />

3.5. 安全性を向上させたもの
----------------

C11のAnnex K Bounds‐checking interfacesで規定された、安全性を向上させた種類が存在する。それぞれ、関数名の末尾に_sを付けた名称となっている。これらの関数は、__STDC_WANT_LIB_EXT1__を1に定義した上で対応するヘッダをインクルードすると宣言される。

define __STDC_WANT_LIB_EXT1__ 1
include
include int printf_s; int fprintf_s; int sprintf_s; int snprintf_s; int vprintf_s; int vfprintf_s; int vsprintf_s; int vsnprintf_s;

int wprintf_s; int fwprintf_s; int swprintf_s; int snwprintf_s; int vwprintf_s; int vfwprintf_s; int vswprintf_s; int vsnwprintf_s;<WtXmlEndTag /> 以下のような機能が追加されている。

FILE*や文字列の引数に対するNULLポインタチェック
%n書式の禁止

4. コード例
-------

include int main { int a = 1234; printf; printf; return 0; }<WtXmlEndTag /> 上記のコードをコンパイルし実行すると、次の出力が得られる。 1234 2322 4d2 abc x

5. 脆弱性
------

一般に、書式文字列を外部や利用者から自由に指定できる状態とすることはセキュリティホールの温床となるため望ましくない。特に%n書式を用いたものが有名である。

6. 他言語
------

C言語から派生したC++やD言語はもとより、PHP、Ruby、Perlなど他の言語でもprintfが実装されている。また、オブジェクト指向の言語の中には、C++でのBoost::format、Ruby、Pythonなど演算子としてsprintfを実行できるものも存在する。

Unix系オペレーティングシステムのコマンドとして実装されたprintf もある。外部コマンドのほか、Bashなど一部のUnixシェルではビルトインで実装されている。

7. 脚注
-----

8. 参考文献
-------

JIS X 3010:2003 プログラミング言語C
[1]}}

9. 関連項目
-------

C言語
入出力
Hello world
scanf
書式文字列攻撃

10. 外部リンク
---------

UNIX コマンド
[2] man page GNU 版。JM Project
[3] man page 
[4] man page
[5] The Open Group Base Specifications Issue 7, 2018 edition
Bashビルトイン: [6]
標準 C ライブラリ
[7] JM Project
[8] man page 
[9] man page