C言語でプログラムを書いているとprintfで文字列を出力する中に自分で定義した構造体の内容を埋め込みたいことがたまにある。
ふつうにやるにはprintfを途中で分割して間で自前の出力ルーチンを呼び出してやることになるが、見通しが悪くなる。
しかしカスタマイズする方法があるということで使ってみた。
注意:gcc拡張で、標準ではない
register_printf_specifier (register_printf_function改め)
「customize printf」とかでググって出てくるページ Customizing Printf (The GNU C Library) を参照して、register_printf_function という関数でできるということを知る。
|
spec:printfのフォーマット指定子に使う文字(%dとかのやつ)render: 出力時に呼び出される関数を指定arginfo: 引数情報を指定するために呼び出される関数を指定
例が載ったページがあるので参照するとよい。
登録するとprintfで標準のフォーマットに加えて独自の出力を追加できる。
ただ手元でやったところ register_printf_function はdeprecatedで register_printf_specifier を使えというエラーが出た。
違いは arginfo にサイズを指定するためのポインタが追加されている
(PA_POINTERの場合は無視しても大丈夫っぽい)。
- 最近のコンパイラでは
printfのフォーマットや引数を見てエラーを出すが、 カスタマイズで追加したことは反映されないのでエラーを抑制してやる必要がある
Macの場合:register_printf_domain_function
上記はLinux/Ubuntu の場合だが、MacOSでは異なっていた。
printfの挙動を変えてしまうと影響が大きいとのことで?、「ドメイン」を用いるようになっている。
ドメインの作成/解放を new_printf_domain(), free_printf_domain() で行い、
登録には register_printf_domain_function 関数を使用する。
出力には明示的に追加のドメイン情報を渡す xprintf 関数で行う。
- 登録関数に渡す関数の型は
register_printf_specifier用とは異なっている (register_printf_functionと同じ) fprintfに対応するのはfxprintf、など
VisualC には?
ググったがカスタマイズする方法は用意されてないっぽい。
例
マクロで辻褄を合わせてLinuxとMacで動かす例:
|
- 環境の違いを吸収するためにマクロで置換する(
REGISTER_PRINTF_SPECIFIER,PRINTF) - 関数の引数の違いを吸収するためにマクロでグルーコードを生成する(
GLUE_PRINTF_ARGINFO_FUNC) - MacOSの場合
- ドメインをグローバル変数
g_domainに保持して使用
- ドメインをグローバル変数
メモ
- 幅指定を使わない前提であればもっと楽できる
- 標準の機能ではないので、依存するのは避けたほうがよさげ
リンク
- c - Is this possible to customize printf? - Stack Overflow
struct printf_infoの説明: Conversion Specifier Options (The GNU C Library)