如何使用GCC属性';格式';?

如何使用GCC属性';格式';?,gcc,attributes,format,warnings,printf,Gcc,Attributes,Format,Warnings,Printf,下面是一段代码: #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 MyVari

下面是一段代码:

#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;
}
前面的警告消失,第16行出现相同的警告(调用
MyPrintf
),这表明
MyVariadicPrintf
可以使用“格式”属性。
因此,我以这种方式添加属性(非常确定这一次是正确的):

现在我在第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);
    }
    
    模板
    void MyVariadicPrintfT(类型常量*格式,…)
    {
    va_列表参数;
    va_开始(参数,格式);
    MyPrintf(格式,args);
    va_端(args);
    }
    
  • 最新的gnu文档可在上找到。
    警告选项位于(查找“-Wmissing format attribute”)。
    函数属性位于(查找“格式(原型、字符串索引、首先检查)”)


    谢谢。

    请看一下。至于最后一个问题,我的猜测是,
    MyPrintf
    不是一个模板函数,唯一可用的定义是将
    char const*
    作为第一个参数,因此它可以安全地提出建议。

    文档中有您需要的答案。特别是:

  • 您发布的是正确的(
    格式(printf,1,0)
    )。1因为格式字符串是参数1,0因为没有要检查的可变参数

  • 在MyVariadicPrintf中,我知道编译器将根据位置1的字符串检查从位置2开始的参数的数量和类型。但是对于MyPrintf,编译器会检查什么?对于MyPrintf,它只会检查格式字符串的有效性(例如,它不是类似于“%\%”的东西)
    void MyVariadicPrintf(char const* format, ...) __attribute__((format(printf, 1, 2)));
    
    template<typename Type>
    void MyVariadicPrintfT(Type const* format, ...)
    {
        va_list args;
        va_start(args, format);
        MyPrintf(format, args);
        va_end(args);
    }