如何使用 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语言学习环境