printf()関数と云へば、先づ頭に浮かぶのは可変変数と云ふ特徴でせう。
printf()関数のやうな可変変数は、どうすれば実現できるのでせう。
int型ではなくvoid型のprintf()もどき関数prf()を作成してみませう。
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> void prf (const char *format, ...) { va_list list; va_start (list, format); (void)vprintf (format, list); va_end (list); } int main (void) { prf ("%d: Hello!\n", 5); return EXIT_SUCCESS; }
可変引数の個数が分つてゐるときは、 formatではなくて、その個数をva_start()に指定できます。 え、型が違ふぢやないか、つて。 大丈夫です、va_start()はマクロ関数なので型確認はされません。 さて、ここからが上級講座。 GCCだけで使へるテクですが、prf()関数を次のやうに書き換えます。
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <assert.h> #include <syslog.h> __attribute__((format(printf,1,2))) void prf (const char *format, ...) { va_list list; assert (NULL != format); va_start (list, format); (void)vprintf (format, list); vsyslog (LOG_ERR, format, list); va_end (list); }
かうしておいてGCCのオプションとして-Wformat=2を指定すると、 自作のprf()関数も本物のprintf()関数と同様に、 フォーマットにリテラルではなく変数を指定して呼び出すと 警告がでるやうになります。 なぜリテラルを指定しなければならないか、については、 「printf()関数 その1」を御覧ください。