如何在字段中存储格式字符串并避免格式非文字警告?

spe*_*goo 0 c++ printf clang

我知道如果函数需要将格式字符串传递到 vsnprintf 中,您可以避免出现__attribute__((__format__ (__printf__, 2, 0)))“格式字符串不是字符串文字”的 clang 警告。但是在我的例子中,格式字符串被保存为一个用文字初始化的字段。像这样的东西:

class Worker {
    const char* format;
    Worker(const char* f): format(f) {...}

    void go() {
        ...
        vsnprintf(..,..,format,..);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免警告?

Jon*_*ler 5

您可以使用#pragma clang diagnostic ignored "-Wformat-nonliteral"或替换clangGCC

#include <cstdio>
#include <cstdarg>

using namespace std;

class Worker {
    const char* format;
    Worker(const char* f): format(f) { }

    void go(int j, ...) {
        char data[256];
        va_list args;
        va_start(args, j);
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wformat-nonliteral"
        vsnprintf(data, sizeof(data), format, args);
        #pragma clang diagnostic pop
        va_end(args);
        fputs(data, stderr);
    }
};
Run Code Online (Sandbox Code Playgroud)

push限制pop诊断处理中的更改范围,以便只有一行免受警告。有关更多信息,请参阅GNU 诊断编译指示Clang 诊断编译指示

上面的代码可以干净地编译:

$ clang -O3 -g -std=c++11 -Wall -Wextra -Werror -Wformat-nonliteral -c clang.cc
Run Code Online (Sandbox Code Playgroud)

它在 GCC 中失败了。替换clangGCC,它可以在 GCC 和 Clang 下干净地编译。

在 Mac OS X 10.9.2 Mavericks 上测试:

  • 海湾合作委员会(g++)4.8.2
  • Clang ( clang) 'Apple LLVM 版本 5.1 (clang-503.0.38)(基于 LLVM 3.4svn)'。