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
に保持して使用
- ドメインをグローバル変数
メモ
- 幅指定を使わない前提であればもっと楽できる
- 標準の機能ではないので、依存するのは避けたほうがよさげ