printf関数

printf関数は標準出力に文字列を出力する関数です。
C言語の基本的な関数のひとつですが、意外に扱いが難しい関数です。

printf関数の第一引数は書式指定文字列という特殊な文字列を指定できます。
書式指定文字列は、printf関数の第二引数以降の値を取り込み、指定の形式に変換して表示します。


printf("第二引数は%d", 123);
第二引数は123

このコードの第一引数の文字列中に%dという文字列が存在します。
この%dは第二引数の123という数値を第一引数に取り込み、10進数で表示するという意味を持ちます。

書式指定文字列を複数使用した場合は第三引数以降の値が表示されます。


printf("%d, %d", 123, 456);
123, 456

このページではprintf関数の書式指定文字列の詳細な使用方法を解説します。
printf関数の類似関数であるfprintf関数、sprintf関数、vprintf関数などの書式指定文字列も同様の使用方法です。

文字列変数をprintf関数で表示する場合、セキュリティ上の理由から、第一引数に文字列変数を指定するのではなく書式指定文字列を使用して表示することが推奨されています。
特に外部から入力された文字列を表示する場合、それを悪用した攻撃の手段になり得ます。


char* str = "abcdef";

//非推奨
printf(str);

//書式指定文字列を使用
printf("%s", str);

printf_s関数

printf関数のセキュリティ強化版にprintf_s関数があります。
printf関数は書式指定文字列にNULLが渡された場合にエラーとなりますが、printf_s関数は書式指定文字列に不正な形式の文字列が渡された場合にもエラーとなります。


//エラーにはならない
printf("%q", 123);

//エラー
printf_s("%q", 123);

書式指定文字列

printf関数の第一引数は書式指定文字列を含む文字列です。

書式指定文字列は変換指定子をひとつ以上含む文字列です。
変換指定子は%記号から始まります。
書式を指定する文字列以外の文字列はそのまま出力されます。

書式指定は以下の説明に登場する順序で指定します。
変換指定子以外の書式指定は省略可能です。

フラグ

フラグは出力位置や書式指定文字列の意味を設定します。
フラグは複数指定でき、順序は任意です。
フラグは省略可能です。

フラグ 説明 既定値
- フィールドの左揃え 右揃え
+ 符号付き数値の前に常に符号を表示する 負数の場合にのみマイナス符号を表示する
0 最小桁数に達するまで空白を0で埋める
整数値の精度指定がされている場合、および-フラグと同時指定された場合は0フラグは無効
空白で埋める
空白 符号付きの数値で符号が表示されない場合、空白で埋める
+フラグと同時に指定された場合は空白フラグは無効
何もしない
# o変換(8進数表記)の場合、先頭に0が追加される
値が0の場合は何もしない
何もしない
x、X変換(16進数表記)の場合、先頭に0x、0Xが追加される
値が0の場合は何もしない
何もしない
e、E、f、F、a、A変換(小数値)の場合、小数点以下の数値を表示しない場合でも小数点を表示する 何もしない
g、G変換(double型)の場合、小数点以下の数値を表示しない場合でも小数点を表示し、続く0を表示する 何もしない
上記以外の変換に#フラグを付けた場合は未定義  

最小フィールド幅

最小フィールド幅は、表示される文字列の最小の文字数を指定します。
指定よりも実際に表示する文字数の方が大きい場合は自動で拡張されます。
最小フィールド幅は省略可能です。

最小フィールド幅は正の整数値またはアスタリスク(*)で指定します。
アスタリスクを指定した場合は第二引数の数値の幅が設定されます。


#include <stdio.h>

int main()
{
	printf("%05d", 123);
	printf("\n");
	printf("%0*d", 7, 123);

	getchar();
}
00123
0000123

何も指定しない場合は空白で埋められます。
上記コードは表示を分かりやすくするために0フラグと組み合わせています。

アスタリスクを使用した場合に負数を最小フィールド幅を指定した場合、-フラグが指定されたものと解釈されます。


#include <stdio.h>

int main()
{
    printf("%0*d", -5, 123);
    printf("あああ");

	getchar();
}
123  あああ

上記のコードは実行結果をわかりやすくするため、直後に「あああ」の文字列を出力しています。
最小フィールド幅に負数を指定しているため、これは-フラグの指定と解釈され、出力が左揃えされた上で「123」の後ろに空白が二文字出力されています。

引数の順序

書式指定文字列内にアスタリスクを指定する変換指定が複数存在する場合、引数は「最小フィールド幅, 変換される値, 最小フィールド幅, 変換される値...」の順となります。


#include <stdio.h>

int main()
{
	printf("%0*d, %0*d", 5, 123, 5, 456);

	getchar();
}
00123, 00456

これは以下の精度指定でも同様です。

精度指定

精度指定は表示する文字列の文字数を指定します。
精度指定は省略可能です。

精度指定はピリオド(.)に続く正の整数値またはアスタリスク(*)で指定します。

アスタリスクを指定した場合は第二引数の数値の幅が設定されます。
引数の順序に関しては最小フィールド幅と同じです。
(引数の順序参照)
アスタリスクを使用する場合に、負数を精度指定にした場合は無視されます。

変換指定子 説明 既定値
d、i、o、u、x、X 最小桁数の指定
指定の値が実際の文字数よりも小さい場合は0で埋める
1
e、E、f、F 小数部(小数点の後ろの数値)の有効桁数の指定
桁の最後は丸められる(四捨五入される)
6
g、G 有効桁数の指定 6
s 有効文字列数 表示される文字列の文字数

上記以外の変換指定子に精度指定をした場合の動作は未定義です。


#include <stdio.h>

int main()
{
	printf("%.5d", 123);
	printf("\n");
	printf("%.5f", 0.123456789);
	printf("\n");
	printf("%.5s", "123456789");

	getchar();
}
00123
0.12346
12345

長さ修飾子

長さ修飾子は実引数のデータ型のサイズを指定します。
長さ修飾子は省略可能です。

長さ修飾子 変換指定子 データ型
hh d、i、o、u、x、X char型、unsigned char型
n char型のポインタ
h d、i、o、u、x、X short型、unsigned short型
n short型のポインタ
l(小文字のL) d、i、o、u、x、X long型、unsigned long型
n long型のポインタ
ll(小文字のLL) d、i、o、u、x、X long long型、unsigned long long型
n long long型のポインタ
L a、A、e、E、f、F、g、G long double型
j d、i、o、u、x、X intmax_t型
(対応する中で最大の整数値を扱うデータ型)
z d、i、o、u、x、X size_t型
t d、i、o、u、x、X ptrdiff_t型
(ポインタ同士を減算した値を扱う型)

以下はMicrosoft独自の拡張です。

長さ修飾子 変換指定子 データ型
l(小文字のL) a、A、e、E、f、F、g、G long double型
h c、C 1バイト文字
I32 d、i、o、u、x、X __int32型、unsigned __int32型
I64 d、i、o、u、x、X __int64型、unsigned __int64型

変換指定子

変換指定子は引数を表示する形式を指定します。
変換指定子はアルファベットまたは記号の一文字で指定します。
変換指定子は省略できません。

変換指定子 説明
d、i 符号付き10進整数
u 符号なし10進整数
o 符号なし8進整数
x、X 符号なし16進整数
xはアルファベットを小文字で表示
Xはアルファベットを大文字で表示
f、F 浮動小数点数
小数を表示(ddd.ddd)
Fはアルファベットを大文字で表示
(無限大、NaN)
e、E 浮動小数点数
小数の指数表記(ddd.ddde±dd)
Eは指数を表すeを大文字で表示
g、G 浮動小数点数
小数の16進指数表記(0xddd.dddp±dd) fまたはeの変換のうち、表示が短い方で表示
指数部が-4より小さい場合、または精度指定以上の場合にeが使用される。
Gはアルファベットを大文字で表示
a、A 16進浮動小数点数
Aはアルファベットを大文字で表示
c 文字
int型の実引数をunsigned char型に変換し、結果を文字で表示
s 文字列
文字列へのポインタを実引数に指定し、null文字が出現する直前まで表示
p ポインタ
任意の型のポインタを実引数に指定し、16進数で表示
n 整数へのポインタ
現時点までに出力された文字数を整数へのポインタに格納する。
※Visual Studioではセキュリティ上の問題で標準では無効
% %を表示
この変換指定子は実引数を取らない

戻り値

printf関数の戻り値は出力された文字列の文字数です。
エラーが発生した場合は負数を返し、errnoEINVALを設定します。

参考