通过man
我找到了
printf("%*d", width, num);
和
printf("%2$*1$d", width, num);
是等价的。
但IMO的第二种风格应该与:
相同 printf("%*d", num, width);
然而,通过测试似乎man
是正确的;为什么呢?
答案 0 :(得分:24)
printf()
的POSIX规范的相关部分定义了这种行为:
转换可以应用于参数列表中格式之后的 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
在这个例子中)和*
。你的推定设计可能会起作用,但不是选择的设计。
答案 1 :(得分:3)
在你的第二个例子中:
printf("%2$*1$d", width, num);
第一个数字2附加到格式说明符,第二个数字1附加到*
。如果您阅读printf
的文档,则很清楚。没有什么不寻常的事情发生。
答案 2 :(得分:1)
字段宽度或精度或两者都可以用星号表示 '*'或星号后跟一个或多个十进制数字和'$' 而不是数字字符串。
因此1$
适用于星号,因此第一个参数是宽度。 2$
适用于整个格式规范,因此第二个参数是将打印其值的参数。
答案 3 :(得分:0)
我同意该手册页令人困惑,因为它在 one <中解释了两个概念(长度修饰符作为位置参数)。 / em>示例,所以我去看看强大的一对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