[英]An Abstrusing printf() expression
POSIX / SUS printf()
允许一个数字,后跟$
后%
,以表明从可变参数的特定参数应该是采摘。
printf("%2$s, %1$s!\n", "world", "Hello");
格式导致:
<num1> 0 <num2>
<num3> <num4> <num3>
<num2> 0 <num1>
所有数字都是0或1,具体取决于稍后的操作结果。 这个格式字符串中唯一不寻常的是使用%<N>$
- 这表示对于这个参数,应该使用函数的arg<N>
(而不是按顺序的“下一个”)。 例如,如果您指定:
printf("%d %1$x\n", 10);
它打印你'10 a'。
它打印三行整数,比如更简单:
printf("%d %d %d\n%d %d %d\n%d %d %d\n", 0, 0, 0, 0, 1, 0, 0, 0, 0);
哪个会打印
0 0 0
0 1 0
0 0 0
%2 $ d表示“使用第二个参数而不是与我的位置对应的参数”
现在,每行中的每列都有一个特定条件,在该点上打印“0”或“1”。 由于骰子的对称性,你真正感兴趣的是以下位置(用x标记):
x 0 x
x x -
- 0 -
其他位置可以从它们( - )导出或始终为0(0)。
这是“聪明的编码”的一个例子,这很有趣,但阅读令人沮丧。
让我们从格式开始( "%d 0 %d\\n%d %d %3$d\\n%2$d 0 %1$d\\n\\n"
):
n > 53
) 对于看起来很滑稽的参数:
此代码不一致且已损坏。 如果使用%N$
-type参数索引说明符,则必须将它们用于所有参数,而不是选择性地用于某些参数而不是其他参数。
固定版本:
printf("%1$d 0 %2$d\n%3$d %4$d %3$d\n%2$d 0 %1$d\n\n",n>50,51%n%2,n>53,n%2);
相关引文如下: http : //www.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
格式可以包含编号参数转换规范(即“%n $”和“* m $”),或无编号参数转换规范(即%和*),但不能同时包含两者。 唯一的例外是%%可以与“%n $”表单混合使用。 在格式字符串中混合编号和未编号参数规范的结果是未定义的。 当使用带编号的参数规范时,指定第N个参数要求在格式字符串中指定从第一个到第(N-1)个的所有前导参数。
这段代码“工作”的事实是printf
函数的特定实现(可能是GNU函数)的副作用。 没有理由期望它在其他系统上工作,甚至在同一系统的未来版本上工作,除非它被记录在该系统上工作。
即使使用我的修复程序,此代码仍然是POSIX特定的; 它不能移植到非POSIX系统上的C实现。 而不是丑陋的黑客,作者应该根据需要复制参数:
printf("%d 0 %d\n%d %d %d\n%d 0 %d\n\n",n>50,51%n%2,n>53,n%2,n>53,51%n%2,n>50);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.