C言語:printfチートシート
根拠となる POSIX 仕様
https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
特定の長さの文字列をバッファに入れるとき
snprintf(buf, sizeof(buf), "%-*.*s", len, len, value);
- 左詰め(パディングありの時)
ピリオド前の* 表示桁数(パディング用) なければパディングなしになる。
ピリオド後の* 取得する最大桁数
code:sample.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("%-10.5s\n", "Hello, world!");
printf("%-10.5s\n", "A");
printf("%10.5s\n", "Hello, world!");
printf("%10.5s\n", "A");
printf("%5.5s\n", "Hello, world!");
printf("%5.5s\n", "A");
printf("%-5.5s\n", "Hello, world!");
printf("%-5.5s\n", "A");
printf("%5.7s\n", "Hello, world!");
printf("%5.7s\n", "A");
printf("%-5.7s\n", "Hello, world!");
printf("%-5.7s\n", "A");
printf("%.5s\n", "Hello, world!");
printf("%.5s\n", "A");
return 0;
}
結果
code:console
Hello
A
Hello
A
Hello
A
Hello
A
Hello,
A
Hello,
A
Hello
A
変換指定子の構文
code:spec.txt
%引数順フラグ最小フィールド幅.精度修飾子変換指定子
引数順
数字 + "$" で引数の場所を指定できる。1つ目の引数は1。
フラグ
table:flag
- フィールドの左寄せ
+ 先頭の文字 正:"+" 0: 負:"-"
空白 先頭の文字 正:" ", 0:" ", 負:"-"
0 フィールドの0埋め
# 代替表示
最小フィールド幅
文字列の場合は、パディングを含めた表示桁数になる。
"*"を指定することができる。その場合、そこに当たる引数(int型固定)を数値として取り込む。
精度
文字列の場合は、データから取り出す最大桁数になる。.だけ指定すると0になってしまう。
"*"を指定することができる。その場合、そこに当たる引数(int型固定)を数値として取り込む。
修飾子
修飾子はデータサイズを示している。
printf は、過去からの互換性のため、int 未満の数値は int 型(符号無しならば unsigned int型)に変換されてから引き渡される。
table:type
hh char
h short
l long, wchar_t, (double)
ll long long
j intmax_t
z size_t
t ptrdiff_t, (ssize_t)
(char が 8bit の場合)
char c = 0xff; // 多くの場合、符号付きと解釈される。
printf("%x", c); // int 型(多くの場合32bit符号付き)に符号拡張されるので、255 ではなく、32bit 値の"ffffffff"になる。
printf("%hhx", c); // "ff" と表示されることが保証される。
変換指定子
table:convert
d, i 10進符号付き整数
u 10進符号無し整数
o 8進符号無し整数
x 16進符号無し整数(英字は小文字)
X 16進符号無し整数(英字は大文字)
f 小数形式
F 小数形式
e 指数形式(指数のeが小文字)
E 指数形式(指数のEが大文字)
g e, f のどちらかを値に応じて切り換え
G E, F のどちらかを値に応じて切り換え
a 16進浮動小数点数(指数が小文字)
A 16進浮動小数点数(指数が大文字)
c 文字出力(char, wchar_t 1つ分)
s ポインタが指す文字列の出力
p ポインタ
n 引数に出力済み文字数を格納(引数に書き込まれるので要注意)
% '%'を出力
変換指定子のnは引数への書き込みになってしまっている。
また、実際の引数の数と書式で指定されている引数の数とが一致しないと、スタックの破壊などを引き起こす。
このため、書式をユーザーからの入力で受け入れている場合、それが脆弱性になってしまう。
どうしても書式をユーザー入力で受け入れたい場合、書式の正当性チェックが必要。
uint64_t などを出力する場合、以下の形式のマクロを使う
"PRI" + 変換指定子 + ビット数
intmax_t の場合 PRIdMAX
uintmax_t の場合 PRIuMAX(PRIxMAX)
code:bitspec.c
#include <stdint.h> // uint64_t などが入っている
#include <inttypes.h> // PRIu64 などが入っている。
...
{
...
uint64_t n;
printf("%" PRIu64, n);