【问题标题】:How to use the GCC attribute 'format'?如何使用 GCC 属性“格式”?
【发布时间】:2009-06-15 15:33:19
【问题描述】:

这是一小段代码:

#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 行(调用MyPrintf),表明MyVariadicPrintf 可以使用“格式”属性。
所以我以这种方式添加属性(很确定这次是对的):

void MyVariadicPrintf(char const* format, ...) __attribute__((format(printf, 1, 2)));

现在我在第 22 行收到了预期的警告(致电 MyVariadicPrintf):

格式参数太少

  1. 我做对了吗?
  2. 我注意到在MyPrintf 声明中,如果我删除了属性部分,我仍然会在第 22 行得到想要的警告。我还注意到在这个属性部分中,将索引从 1 更改为 2 不会给出任何警告或错误。哪一个是正确的,这个函数的属性的目标是什么?
  3. 如果我添加以下函数MyVariadicPrintfT 并调用它(专用于char),我将收到建议在此函数上使用“格式”属性的警告。我认为这是不可能的,因为 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(查找“格式(原型,字符串索引,首先检查)”)。

谢谢。

【问题讨论】:

    标签: gcc attributes format warnings printf


    【解决方案1】:

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

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

    【讨论】:

    • 在 MyVariadicPrintf 中,我知道编译器会根据位置 1 的字符串检查从位置 2 开始的参数的数量和类型。但是对于 MyPrintf,编译器会检查什么?
    • 在 MyPrintf 的情况下,它只会检查格式字符串的有效性(例如,它不是像“%_%”这样的东西)
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      • 2019-04-10
      • 2015-10-07
      相关资源
      最近更新 更多