通过man
命令我找到了
printf("%*d", width, num);
并且
printf("%2$*1$d", width, num);
等价。
但在我看来,第二种样式应该与以下样式相同:
printf("%*d", num, width);
然而通过测试,似乎man
是正确的;为什么呢?
printf()
相关的部分定义了以下行为:
转换可以应用于格式后的第n个参数,而不是下一个未使用的参数。在这种情况下,转换说明符字符%(请参见下文)将替换为序列“%n $”,其中n是取值范围为[1,{NL_ARGMAX}]的十进制整数,表示参数在参数列表中的位置。此功能提供了定义格式字符串以选择按特定语言适当顺序排列的参数的可能性(请参见“示例”部分)。
格式可以包含编号的参数转换规范(即“%n $”和“* m $”),也可以包含非编号的参数转换规范(即%和*),但不能同时使用。唯一的例外是%%可以与“%n $”形式混合。在格式字符串中混合编号和非编号参数规范的结果未定义。当使用编号的参数规范时,指定第N个参数要求在格式字符串中指定所有前导参数,从第一个到(N-1)个。
在包含转换规范“%n $”形式的格式字符串中,可以根据需要多次引用参数列表中的编号参数。
%n$
标识要打印值的参数-您示例中的第2个参数。
* n $
标识要视为格式宽度的值的参数-您示例中的第1个参数。
因此,编写手册的人遵循了标准。
您在评论中提出了争议:
2$*
应该匹配第二个参数,而1$d
应该匹配第一个参数,但是在printf("%2$*1$d", width, num);
的情况下,却不是这样。正如已经指出的,标准明确将
n$
部分作为%
和*
的后缀修饰符,而不是格式转换说明符(本例中的d
)和*
的前缀修饰符。你所设计的方案可能可以工作,但不是被选择的设计。
printf("%2$*1$d", width, num);
*
相连。如果您阅读printf
的文档,这一点是很清楚的。没有发生任何不寻常的事情。vi
/gcc
。
test.c
#include <stdio.h>
void main(int argc, char** argv) {
printf("%1$c\n", 'a', 'b', 'c');
printf("%2$c\n", 'a', 'b', 'c');
printf("%3$c\n", 'a', 'b', 'c');
printf("%3$c %2$c %1$c\n", 'a', 'b', 'c');
}
$ gcc test.c
test.c: In function ‘main’:
test.c:3:9: warning: unused arguments in $-style format [-Wformat-extra-args]
printf("%1$d\n", 'a', 'b', 'c');
^~~~~~~~
test.c:4:9: warning: format argument 1 unused before used argument 2 in $-style format [-Wformat=]
printf("%2$d\n", 'a', 'b', 'c');
^~~~~~~~
test.c:4:9: warning: unused arguments in $-style format [-Wformat-extra-args]
test.c:5:9: warning: format argument 1 unused before used argument 3 in $-style format [-Wformat=]
printf("%3$d\n", 'a', 'b', 'c');
^~~~~~~~
test.c:5:9: warning: format argument 2 unused before used argument 3 in $-style format [-Wformat=]
$ ./a.out
a
b
c
c b a
2$*
应该匹配第二个参数,而1$d
应该匹配第一个参数,但是在printf("%2$*1$d", width, num);
的情况下并不成立。 - Je Rog