2009-06-15 24 views
13

这里是一个小的一段代码:如何使用GCC属性'格式'?

#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; 
} 

我与GCC 4.0编译它,在Mac OS X Leopard中运行的Xcode。
-Wformat和-Wmissing-format-attribute已启用。
该代码给出了第9行(调用vprintf)一个警告,提示MyPrintf可以使用“格式”属性:

功能可能是“printf”式的格式属性的备选

所以我添加的属性这样(不知道这是正确的):

void MyPrintf(char const* format, va_list args) __attribute__((format(printf, 1, 0))); 

先前警告消失,同样的警告现在出现在第16行(CA从011到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找到。
警告选项在section 3.8(查找“-Wmissing-format-attribute”)。
函数属性在section 6.30(查找“格式(原型,字符串索引,首先检查)”)。

谢谢。

回答

10

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

  1. 您已发布的一个是正确的(format(printf, 1, 0))。 1,因为格式字符串是参数1,0,因为没有可变参数需要检查。
+1

在MyVariadicPrintf中,我明白编译器会检查从位置2开始的参数的数量和类型,而不是位置1处的字符串。但是在MyPrintf的情况下,编译器检查了什么? – Guillaume 2009-06-16 15:10:54

3

看看GCC docs on gnu.org。至于最后一个问题,我的猜测是MyPrintf不是一个模板函数,唯一可用的定义需要char const*作为第一个参数,所以感觉安全的建议。