「__printflike__修飾子」とは正確には何ですか? この用語はどういう意味ですか?
3 に答える
推測では、関数がへの引数のように見える形式[anything, ] format, ...
で引数を取ることを使用しているコンパイラに伝えます。この属性により、コンパイラは文字列形式に対して引数リストの型をテストできます。これは、文字列を何らかの特別なログ インターフェイスに送信する前に、書式設定作業を通常の標準ライブラリ関数に従属させるために、関数 like and useを記述した場合に発生します。format, ...
printf
__printflike__
log(format, ...)
vsprintf
GCC を使用している場合は、おそらく#define
プロジェクトに次のようなものがあります。
#define __printflike__ __attribute__((format(printf, 1, 2)))
whereは、位置 1 と 2 に表示される1, 2
ことを意味します。format, ...
エラー報告ライブラリに、ヘッダーに次のような宣言を持つ関数があります。
extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...)
PRINTFLIKE(4,5);
PRINTFLIKE は大文字なので、GCC を使用していないときは何も定義しないようにしています。この使用法は、最初の 3 つの引数は特別なものではないことを示していますが、4 番目の引数は で使用されるようなフォーマット文字列でありprintf()
(実際、内部的には に渡されvfprintf()
ます)、それに対応する引数 (フォーマット文字列を使用してフォーマットされます) が開始されます。 5 番目の引数で。
これは、次のように入力すると次のことを意味します。
err_logmsg(stdout, ERR_ABORT, 1, "%s: %d\n", errno, strerror(errno));
が文字列へのポインターを返すため、コンパイル エラーが発生errno
します。書式文字列または 5 番目と 6 番目の引数を変更することでエラーを修正できます。(ERR_ABORT は、宣言する同じヘッダーで定義されたフラグのセットです。)int
strerror(errno)
err_logmsg()
PRINTFLIKE マクロには 2 つの数字があります。これは、フォーマット文字列とフォーマット文字列で使用される最初の引数の間に他の引数が存在する可能性があるためです。たとえば、代替関数は次のようになります。
extern void err_writer(FILE *fp, const char *format, int flags, int estat, ...)
PRINTFLIKE(2,5);
これは、書式文字列が 2 番目の引数であることをコンパイラに伝えますが、書式設定される対応する引数は 5 番目の引数から始まるように表示されます。
このコードのヘッダー ファイルには、次の行が含まれています。
#ifdef __GNUC__
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#define NORETURN() __attribute__((noreturn))
#else
#define PRINTFLIKE(n,m) /* If only */
#define NORETURN() /* If only */
#endif /* __GNUC__ */
printf
おそらく、対応する関数に-のようなセマンティクスがあることをコンパイラーに伝えます。
これにより、コンパイラは、書式文字列の修飾子が渡された引数の型または数に対応していない場合に、コンパイル時に警告を発行できます。
、、などを呼び出すときに%u
、 の正しい書式設定ではないことをコンパイラが認識できるようにする方法は他にありません。int
printf
sprintf
fprintf
私は数ヶ月前に逆の質問をしました: printf/sprintf コンパイラの警告は概念的な中断ですか?