systemdには_printf_
というマクロがある。
src/shared/macro.h
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
GCC拡張のformat
属性を簡単に指定するためのもので、関数宣言に指定して使われる。
src/shared/log.h
int log_meta(
int level,
const char*file,
int line,
const char *func,
const char *format, ...) _printf_(5,6);
定義からなんとなく推測できるように、このマクロを指定しておくと、指定した関数の引数がprintf
フォーマットを満たしているかどうか、コンパイル時にチェックしてくれるようになる。引数をprintf系の標準ライブラリ関数にそのまま渡すような関数でも、コンパイル時チェック対象にすることができる。
format
属性についてもうちょっと説明する。format
属性は3つの引数を取り、第一引数はフォーマット種別、第二引数はフォーマット文字列の引数の位置、第三引数はフォーマット文字列でチェックされる引数の最初の位置を指定する。フォーマット種別には、printf
やscanf
といった標準ライブラリ関数のもの以外にも、MinGWやglibcの拡張に対応したフォーマットを指定可能である(ms_printf
やgnu_printf
)。
より詳しくは、GCCのドキュメントを参照のこと。