像“1 $”这样的位置参数如何与printf()一起使用?

时间:2011-06-12 14:41:32

标签: c format printf

通过man我找到了

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

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

是等价的。

但IMO的第二种风格应该与:

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

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

4 个答案:

答案 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