GNU C中printf格式规范param-no的正确用法咨询
printf格式规范中param-no用法的验证与疑问
我正在开发一个基于printf格式字符串的辅助函数,因此深入研究了printf的格式规范,发现GNU手册支持param-no特性。之前从未用过这个特性,为了让函数能兼容所有合法的格式规范,我做了一系列实验:
#include <stdio.h> int main() { double u = 1.23456789; double d = 9.87654321; // 示例A 1. 2. 3. printf( "A) Testing param-no: >%3$*.*f<\n", 12, 3, u ); // 编译器警告:格式中缺少$操作数 // 可正常运行 // // 示例B 1. 2. 3. // printf( "B) Testing param-no: >%1$*.*f<\n", 12, 3, u ); // // 编译器警告:格式中缺少$操作数 // // 无限打印空格 // 示例C 1. 2. 3. printf( "C) Testing param-no: >%3$*.*f<\n", u, 12, 3 ); // 编译器警告:格式中缺少$操作数 // 可正常运行 // // 示例D 1. 2. 3. // printf( "D) Testing param-no: >%1$*.*f<\n", u, 12, 3 ); // // 编译器警告:格式中缺少$操作数 // // 无限打印空格 // 示例E 1. 2. 3. 4. 5. 6. printf( "E) Testing param-no: >%3$*.*f<, >%6$*.*f<\n", 12, 3, u, 5, 4, d ); // 编译器警告:格式中缺少$操作数 // 输出错误:"Testing param-no: > 0.000<, >1.2346<" // 示例F 1. 2. 3. 4. 5. 6. printf( "F) Testing param-no: >%3$*.*f<, >%6$*.*f<\n", u, 12, 3, d, 5, 4 ); // 编译器警告:格式中缺少$操作数 // 输出错误:"Testing param-no: > 0.000<, >1.2346<" // 示例G 1. 2. 3. printf( "G) Testing param-no: >%3$*1$.*2$f<\n", 12, 3, u ); // 可正常运行 // 示例H 1. 2. 3. 4. 5. 6. printf( "H) Testing param-no: >%3$*1$.*2$f<, >%6$*4$.*5$f<\n", 12, 3, u, 5, 4, d ); // 可正常运行 // 示例I 1. 2. 3. 4. 5. 6. printf( "I) Testing param-no: >%1$*2$.*3$f<, >%4$*5$.*6$f<\n", u, 12, 3, d, 5, 4 ); // 可正常运行 // 示例J 1. 2. 3. 4. 5. 6. printf( "J) Testing param-no: >%4$*5$.*6$f<, >%1$*2$.*3$f<\n", u, 12, 3, d, 5, 4 ); // 可正常运行 // 示例K 1. 2. 3. 4. 5. 6. printf( "K) Testing param-no: >%1$*3$.*6$f<, >%5$*2$.*4$f<\n", d, 12, 5, 3, u, 4 ); // 可正常运行 return 0; }
基于实验结果,我发现参考的GNU文档存在以下误导性内容:
- 转换规范的第二种通用形式
% [ param-no $ ] flags width . * [ param-no $ ] type conversion暗示可以仅用*作为精度并省略param-no$(比如示例A),但实际这么写会触发编译器警告,还可能导致程序异常(比如示例D的无限打印空格)。 - 文档提到
*表示使用参数列表中的下一个参数作为宽度/精度,我原本以为会从指定的实际参数位置向前取值,但这种用法不仅会触发警告,还会导致输出错误(比如示例E)。 - 文档只展示了两种转换规范形式,容易让人误以为无法同时用参数设置宽度和精度,但示例H证明这种用法是可行的。
我猜想正确的描述应该是:
printf模板字符串中的所有转换规范必须统一为以下两种形式之一:
% flags [ width-digits | * ] [ . precision-digits | . * ] type conversion
或% param-no-a $ flags [ width-digits | * param-no-b $ ] [ . precision-digits | . * param-no-c $ ] type conversion
必填的param-no-a指定实际参数的位置,可选的param-no-b和param-no-c分别指定宽度和精度参数的位置。
请问我所参考的GNU文档描述是否准确?我对param-no用法的理解是否正确?
内容的提问来源于stack exchange,提问作者z32a7ul
相关产品推荐
相关产品推荐

