如何使用 GCC 属性“格式”?

Posted

技术标签:

【中文标题】如何使用 GCC 属性“格式”?【英文标题】:How to use the GCC attribute 'format'? 【发布时间】: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):

格式参数太少

    我做对了吗? 我注意到在MyPrintf 声明中,如果我删除了属性部分,我仍然会在第 22 行得到想要的警告。我还注意到在这个属性部分中,将索引从 1 更改为 2 不会给出任何警告或错误。哪一个是正确的,这个函数的属性的目标是什么?

    如果我添加以下函数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(查找“格式(原型,字符串索引,首先检查)”)。

谢谢。

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

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

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

【讨论】:

以上是关于如何使用 GCC 属性“格式”?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Notepad++和GCC搭建Windows下的C语言学习环境

如何使用Notepad++和GCC搭建Windows下的C语言学习环境

gcc 链接器如何获取函数的大小?

是否有可以将 Visual Studio 目标文件转换为 GCC 格式的工具?

如何指定GCC的默认头文件路径

安装linux时如何安装GCC