printf()中的位置参数如何使用,例如“1$”?

20

通过man命令我找到了

               printf("%*d", width, num);

并且

               printf("%2$*1$d", width, num);

等价。

但在我看来,第二种样式应该与以下样式相同:

               printf("%*d", num, width);

然而通过测试,似乎man是正确的;为什么呢?


2
2$* 应该匹配第二个参数,而 1$d 应该匹配第一个参数,但是在 printf("%2$*1$d", width, num); 的情况下并不成立。 - Je Rog
4个回答

31
POSIX规范中与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)和*的前缀修饰符。你所设计的方案可能可以工作,但不是被选择的设计。


5
在你的第二个例子中:
printf("%2$*1$d", width, num);

第一个数字2与格式说明符相连,第二个数字1与*相连。如果您阅读printf的文档,这一点是很清楚的。没有发生任何不寻常的事情。

1
一个字段宽度或精度,或者两者都可以通过星号 '*' 或者跟随着一个或多个十进制数字和一个 '$' 的星号来指示代替数字字符串。
所以`1$`适用于星号,因此第一个参数是宽度。`2$`适用于整个格式规范,因此第二个参数是将要打印出其值的参数。

1
我同意,man文档说明了两个概念(长度修饰符和位置参数),在一个例子中容易令人困惑。因此,我去使用强大的组合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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接