14

ここに小さなコードがあります:

#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)で予期される警告が表示されます。

フォーマットの引数が少なすぎます

  1. 私はこれを正しく行いましたか?
  2. MyPrintf宣言時に、属性部分を削除しても、22 行目で必要な警告が引き続き表示されることに気付きました。また、この属性部分で、インデックスを 1 から 2 に変更しても、警告やエラーが発生しないことにも気付きました。どちらが正しいで、この関数の属性の目的は何ですか?
  3. 次の関数を追加して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)" を探してください)。

ありがとう。

4

2 に答える 2

11

ドキュメントには、必要な答えがあります。特に:

  1. はい
  2. あなたが投稿したものは正しいです ( format(printf, 1, 0))。1 はフォーマット文字列がパラメーター 1 であるため、0 はチェックする可変引数がないためです。
于 2009-06-15T15:53:25.973 に答える
4

gnu.orgの GCC ドキュメントを見てください。MyPrintf最後の質問については、それはテンプレート関数ではなく、利用可能な唯一の定義char const*が最初の引数として使用されるため、安全に提案できると思います。

于 2009-06-15T15:47:13.047 に答える