重复 printf 说明符标志时的行为是什么?
What is the behavior when a printf specifier flag is repeated?
fprintf()
函数族有 5 个 flag 个字符 '-'
, '+'
, ' '
, '#'
, '0'
.
当标志被重复时,指定的行为是什么(如果有)?
#include <stdio.h>
int main(void) {
printf("% d\n", 12); // 12
printf("%00d\n", 34); // 34
printf("%++d\n", 56); // +56
printf("%00*d\n", 5, 78); // 00078
return 0;
}
使用我的 gcc "i686-pc-cygwin/4.9.2" 我收到 "warning: repeated ' ' flag in format [-Wformat=]",所以我认为这是正确的行为 --> 警告用户并允许重复标志。
我还没有找到 C99/C11 规范指南来解决在尝试编写格式解析器时发现的这个角落问题。
如果允许重复,下面的代码就OK了。如果不允许重复,第二个0
就是宽度。那么说明符有2个宽度0
和*
,又是一个问题
// -------v
printf("%00*d\n", 5, 78); // 00078
在C标准(7.21.6.1 fprintf函数)中只写了
4 Each conversion specification is introduced by the character %.
After the %, the following appear in sequence:
— Zero or more flags (in any order) that modify the meaning of the
conversion specification.
所以我想标志可能会重复。否则会有一些限制。
标准说:
7.19.6.1/4 Zero or more flags (in any order) that modify the meaning of the conversion specification.
"zero or more flags" 显然是为了允许指定多个标志。这是有道理的,如果一个标志重复出现,它与只出现一次的标志具有相同的含义。
在我看来,标准在这一点上并不清楚。
gcc 的作者明确认为重复的标志是无效的,因为 gcc 默认会发出如下警告:
printf("%++d\n", 42);
但这并不一定能告诉我们标准作者的意图。
标准允许:
Zero or more flags (in any order) that modify the meaning of the conversion
specification.
标志是 -
、+
、space、#
和 0
。我认为,“零个或多个标志*”这个短语专门用于允许 不同的 标志组合。例如,这个:
#include <stdio.h>
int main(void) {
printf("|%6x|\n", 0x123);
printf("|%-6x|\n", 0x123);
printf("|%#6x|\n", 0x123);
printf("|%-#6x|\n", 0x123);
printf("|%#-6x|\n", 0x123);
}
有效并产生此输出:
| 123|
|123 |
| 0x123|
|0x123 |
|0x123 |
在其他情况下,该标准明确规定了构造是否可以重复。例如,long long int
不同于 long int
,而 long int int
是语法错误。另一方面,该标准明确指出 (N1570 6.7.3p5):
If the same qualifier appears more than once in the same
specifier-qualifier-list, either directly or via one or more
typedefs
, the behavior is the same as if it appeared only once.
这里没有任何这样的声明让我怀疑标准的作者没有考虑重复相同标志的情况。
如果我对此有误,并且委员会确实打算将重复的标志等同于单个标志,那么您的格式解析器应该将它们视为等同的。如果我是正确的,那么重复相同标志的行为是未定义的,并且您的实现可以做任何您喜欢的事情——包括将它们视为等同于单个标志。
无论哪种情况,您都可以随意发出警告。即使标准定义了重复标志的行为,它仍然可以说是糟糕的风格,值得警告。
fprintf()
函数族有 5 个 flag 个字符 '-'
, '+'
, ' '
, '#'
, '0'
.
当标志被重复时,指定的行为是什么(如果有)?
#include <stdio.h>
int main(void) {
printf("% d\n", 12); // 12
printf("%00d\n", 34); // 34
printf("%++d\n", 56); // +56
printf("%00*d\n", 5, 78); // 00078
return 0;
}
使用我的 gcc "i686-pc-cygwin/4.9.2" 我收到 "warning: repeated ' ' flag in format [-Wformat=]",所以我认为这是正确的行为 --> 警告用户并允许重复标志。
我还没有找到 C99/C11 规范指南来解决在尝试编写格式解析器时发现的这个角落问题。
如果允许重复,下面的代码就OK了。如果不允许重复,第二个0
就是宽度。那么说明符有2个宽度0
和*
,又是一个问题
// -------v
printf("%00*d\n", 5, 78); // 00078
在C标准(7.21.6.1 fprintf函数)中只写了
4 Each conversion specification is introduced by the character %. After the %, the following appear in sequence:
— Zero or more flags (in any order) that modify the meaning of the conversion specification.
所以我想标志可能会重复。否则会有一些限制。
标准说:
7.19.6.1/4 Zero or more flags (in any order) that modify the meaning of the conversion specification.
"zero or more flags" 显然是为了允许指定多个标志。这是有道理的,如果一个标志重复出现,它与只出现一次的标志具有相同的含义。
在我看来,标准在这一点上并不清楚。
gcc 的作者明确认为重复的标志是无效的,因为 gcc 默认会发出如下警告:
printf("%++d\n", 42);
但这并不一定能告诉我们标准作者的意图。
标准允许:
Zero or more flags (in any order) that modify the meaning of the conversion specification.
标志是 -
、+
、space、#
和 0
。我认为,“零个或多个标志*”这个短语专门用于允许 不同的 标志组合。例如,这个:
#include <stdio.h>
int main(void) {
printf("|%6x|\n", 0x123);
printf("|%-6x|\n", 0x123);
printf("|%#6x|\n", 0x123);
printf("|%-#6x|\n", 0x123);
printf("|%#-6x|\n", 0x123);
}
有效并产生此输出:
| 123|
|123 |
| 0x123|
|0x123 |
|0x123 |
在其他情况下,该标准明确规定了构造是否可以重复。例如,long long int
不同于 long int
,而 long int int
是语法错误。另一方面,该标准明确指出 (N1570 6.7.3p5):
If the same qualifier appears more than once in the same specifier-qualifier-list, either directly or via one or more
typedefs
, the behavior is the same as if it appeared only once.
这里没有任何这样的声明让我怀疑标准的作者没有考虑重复相同标志的情况。
如果我对此有误,并且委员会确实打算将重复的标志等同于单个标志,那么您的格式解析器应该将它们视为等同的。如果我是正确的,那么重复相同标志的行为是未定义的,并且您的实现可以做任何您喜欢的事情——包括将它们视为等同于单个标志。
无论哪种情况,您都可以随意发出警告。即使标准定义了重复标志的行为,它仍然可以说是糟糕的风格,值得警告。