ここに小さなコードがあります:
#include <stdio.h>
#include <stdarg.h>
void MyPrintf(char const* format, va_list args);
void MyVariadicPrintf(char const* format, ...);
void MyPrintf(char const* format, va_list args)
{
vprintf(format, args);
}
void MyVariadicPrintf(char const* format, ...)
{
va_list args;
va_start(args, format);
MyPrintf(format, args);
va_end(args);
}
int main(int, char*)
{
MyVariadicPrintf("%s" /* missing 2nd argument */);
return 0;
}
Mac OS X Leopard で Xcode を実行して、GCC 4.0 でコンパイルしています。
-Wformat および -Wmissing-format-attribute が有効になっています。
このコードは、9 行目 ( への呼び出し) で警告を表示し、「format」属性を使用できることvprintf
を示唆しています。MyPrintf
関数は「printf」フォーマット属性の候補になる可能性があります
したがって、この方法で属性を追加します(これが正しいかどうかはわかりません):
void MyPrintf(char const* format, va_list args) __attribute__((format(printf, 1, 0)));
前の警告は消え、同じ警告が 16 行目 ( への呼び出し) に表示され、'format' 属性を使用できることがMyPrintf
示唆されます。
だから私はこのように属性を追加します(今回はこれが正しいと確信しています):MyVariadicPrintf
void MyVariadicPrintf(char const* format, ...) __attribute__((format(printf, 1, 2)));
そして、22 行目 ( への呼び出しMyVariadicPrintf
)で予期される警告が表示されます。
フォーマットの引数が少なすぎます
- 私はこれを正しく行いましたか?
MyPrintf
宣言時に、属性部分を削除しても、22 行目で必要な警告が引き続き表示されることに気付きました。また、この属性部分で、インデックスを 1 から 2 に変更しても、警告やエラーが発生しないことにも気付きました。どちらが正しいで、この関数の属性の目的は何ですか?次の関数を追加して
MyVariadicPrintfT
呼び出すと ( で特化char
)、この関数で 'format' 属性を使用することを提案する警告が表示されます。format
引数がテンプレート化された型に依存しているため、それは不可能だと思います。私は正しいですか?template<typename Type> void MyVariadicPrintfT(Type const* format, ...) { va_list args; va_start(args, format); MyPrintf(format, args); va_end(args); }
最新の gnu ドキュメントはgnu.orgにあります。
警告 オプションはセクション 3.8にあります (「-Wmissing-format-attribute」を探してください)。
関数の属性はセクション 6.30にあります ("format (archetype, string-index, first-to-check)" を探してください)。
ありがとう。