没有参数的格式说明符

Format specifier without argument

考虑以下代码示例:

#define STRING_LITERAL  "%u, %u"
const char string_const[ ] = "%u, %u";

snprintf(dest_buff, sizeof(dest_buff), STRING_LITERAL, arg1, arg2, arg3);

然后我的编译器发出警告:格式字符串在此参数之前结束

现在,如果我将指令更改为:

snprintf(dest_buff, sizeof(dest_buff), string_const, arg1, arg2, arg3);

然后编译器不会发出警告。

我的问题是:这样的行为是否符合C99标准?

My question is: does such a behavior comply with C99 standard?

两个示例都调用了未定义的行为,但没有违反约束或语法规则,因此不需要诊断。

警告由编译器生成,它能够确定您向调用传递了不正确的参数,而在第二个调用中没有。

标准定义使用不正确的标志传递不正确的参数 and/or 会导致未定义的行为。

该警告不是标准所要求的,它只是对程序员的额外帮助。

你的参数太多,应该是:

#define STRING_LITERAL  "%u, %u"
snprintf(dest_buff, sizeof(dest_buff), STRING_LITERAL, arg1, arg2);

或:

#define STRING_LITERAL  "%u, %u, %u"
snprintf(dest_buff, sizeof(dest_buff), STRING_LITERAL, arg1, arg2, arg3);

没有警告的原因是它是未定义的行为,只有当编译器足够聪明,认为有问题时才会发出警告。如果字符串是直接在 snprintf 命令中,编译器似乎足够聪明,如果字符串是间接传递的,它似乎不是。

在这个例子中

snprintf(dest_buff, sizeof(dest_buff), STRING_LITERAL, arg1, arg2, arg3);

你直接传递了一个字符串文字,而在这个

snprintf(dest_buff, sizeof(dest_buff), string_const, arg1, arg2, arg3);

您正在传递一个变量。

我假设您的编译器(无论是哪个编译器)出于相关警告的目的将文字与变量区别对待。

我在 C99 标准的附录 I(常见警告)中找到了以下声明,阐明了这种情况。

1 An implementation may generate warnings in many situations, none of which are specified as part of this International Standard. The following are a few of the more common situations.