我对c中的属性格式说明符感到困惑。我在编译一些代码时遇到了一个警告。以下是警告:
警告:格式的参数太多 [-W 格式-额外参数]
下面是一个示例代码:
#include <stdio.h>
void test (int a, int b, const char* ax, const char* bx)__attribute__((format (printf, 3, 0)));
int main()
{
char * a = "abc";
char* b = "cde";
test(1,2,NULL,NULL); /*produces warning*/
test(1,2,a,NULL); /* does not produce warning */
}
void test(int a, int b, const char* ax, const char* bx)
{
printf("hello");
}
输出如下:
gcc -o asn.o test.c
test.c: In function ‘main’:
test.c:7:5: warning: too many arguments for format [-Wformat-extra-args]
test(1,2,NULL,NULL); /*produces warning*/
^~~~
只要满足以下条件(基于实验),就会发出警告:
以下代码似乎工作正常,这让我相信NULL是一个有效的字符串,因为它只是检查一致性:
#include <stdio.h>
void test (int a, int b, const char* ax)__attribute__((format (printf, 3, 0)));
int main()
{
char * a = "abc";
char* b = "cde";
test(1,2,NULL);
test(1,2,a);
}
void test(int a, int b, const char* ax)
{
printf("hello");
}
有人能给我解释一下这种行为吗?它与属性格式说明符中的NULL或零有关吗?我正在使用gcc 7.2.0
编辑:
讨论中的一些更多信息。这里的问题是,这不是一个可变参数函数,因此第三个参数作为零传递。文档提到了这一点
对于无法检查参数的函数(如 vprintf),请将第三个参数指定为零。
由于NULL是一个“一致”字符串,我认为它不应该发出警告。另外,重申这不是我的代码,而是来自一个众所周知的库。
编辑 2:
在尝试更多的东西时,我发现vsnprintf使用了类似的签名。将NULL传递给格式字符串会导致三个警告
warning: null argument where non-null required (argument 3) [-Wnonnull]
vsnprintf (buffer,256,NULL, args);
^~~~~~~~~
testvsn.c:10:31: warning: too many arguments for format [-Wformat-extra-args]
vsnprintf (buffer,256,NULL, args);
^~~~
testvsn.c:10:3: warning: null format string [-Wformat-truncation=]
vsnprintf (buffer,256,NULL, args);
在这一点上,我相信作为字符串传递的NULL只是未定义的行为或函数,使用上面的定义不应该允许NULL字符串。如果有人能给出具体的答案,我将不胜感激。
如果我删除__attribute__
碎屑,则使用GCC 7.2.1时警告会消失。如果我把它留在 -W 格式 -W格式 -额外参数 中,
它就会留下来。
您指定test
在位置3接受格式字符串,然后接受零个附加参数。这当然与您的函数完全矛盾。
< code>printf属性指令是GCC为varargs类型函数发出警告的方式,在这种情况下,您需要验证是否已经传入了一定数量的参数,否则您必须在运行时执行这些操作。这不是你正在做的事情,所以你不应该使用那个指令。
每当你遇到像这样不熟悉的东西时,在盲目使用它们之前,花点时间阅读留档以更好地理解它们的目的。
简短的回答:不要无缘无故地使用__attribute__
。
对于printf
系列函数,NULL
不是有效的格式字符串。它会导致未定义的行为将NULL
作为格式字符串传递给标准库函数。
你张贴的证据表明,gcc似乎不支持你所希望的行为,即“只做格式检查,如果参数非空”。
也许你可以提交一个错误报告,“格式参数太多”的消息肯定是无稽之谈。我猜它假设vprintf
模式是由于0
的最后一个参数,但它变得混乱,因为实际上没有va_list
参数。
请注意,为格式字符串使用变量(即a
)意味着无论如何都无法检查字符串。它只检查格式字符串是字符串文字的情况;它不会尝试进行任何静态分析来跟踪变量的来源。您可以通过执行char*a="%y"; test(1,2, a, NULL);
与test(1,2,"%y", NULL);
来测试这一点。
现在,编辑器在使用注释方法的地方显示警告。然后显示使用的建议。当我接受它的更改时,它会将代码转换为此,警告消失。 使用有意义吗? 实现是 所以如果为空,我的代码仍然会崩溃。 我们应该对此进行空检查。 我认为比好,你说呢?如果是,则编辑器不应建议在此处使用。 因为在具有状态(如)的字段中使用要求NonNull是不安全的。我是否错过了的一些好处?
当我尝试编译它时,我收到以下错误,不知道为什么…… 警告:格式“%x”需要类型为“unsigned int”的参数,但参数2的类型为“char *”[-w format =] 代码:
本文向大家介绍Fortran 分配格式说明符,包括了Fortran 分配格式说明符的使用技巧和注意事项,需要的朋友参考一下 示例 在Fortran 95之前,可以将分配的格式用于输入或输出。考虑 该assign语句将语句标签分配给整数变量。以后将此整数变量用作print语句中的格式说明符。 在Fortran 95中删除了这种格式说明符分配。相反,更现代的代码可以使用其他形式的执行流控制 或字符变量
说我想打印: 这是正确的。这: 或者这个: ? 事情是在其他地方,所以我遇到了这样的讨论: -即使ch变为无符号字符,代码的行为也不是由C标准定义的。这是因为无符号字符被提升为int(在普通的C实现中),所以int被传递给printf的说明符%u。但是,%u需要一个无符号int,所以类型不匹配,并且C标准没有定义该行为 -你的评论不正确。C11标准规定转换说明符必须与函数参数本身的类型相同,而不是
设置一个应该在图像上放置广告的应用程序时,我在运行代码时遇到了这个WordPress错误,这是一个令人沮丧的星期试图修复这个问题。 我希望它能工作,但它给了我以下错误:警告:preg_replace_callback():需要参数2,' 如果有人能想出一个解决方案,那将是惊人的,非常感谢!
我刚刚更新了PHP在我的服务器从PHP 5到PHP 7,我得到了这些警告: 警告:preg_replace_callback()[function.preg-replace-callback0]:要求参数2“chr(\1)”是有效的回调 警告:preg\u replace\u callback() 警告:preg_replace_callback()[function.preg-replace-c