printf和cast float参数

作为我的程序的一部分,我使用:

int ret = vprintf (format, args); 

我进入堆栈的args ,我不知道实际上是什么被推到了堆栈上。 格式是一个字符串,我可以阅读。

上述方法有效,直到我必须打印浮点数。 当我打印浮动时,我得到一些奇怪的数字……

我检查了如果我调用float fArg = *(reinterpret_cast(args) – 然后打印fArg打印正确的值(当args仅由一个实际参数组成时我尝试过)

所以我可能需要"%...f"子格式的特殊行为 – 相应的(子)参数应该转换为float。 ( ...符号表示在f之前可以添加精度,宽度等)我如何实现它?

请注意,对于可变长度参数列表,所有float值都将提升为(并传递为) double值。 你无法可靠地使用:

 float f = va_arg(args, float); /* BAD! */ 

因为语言永远不会在堆栈上放置浮点值。 你必须写:

 float f = va_arg(args, double); /* OK */ 

这可能是你的整个问题。


如果没有,您可能需要扫描格式字符串,并隔离格式说明符,并实现核心printf()代码的重要部分。 对于每个说明符,您可以从args收集适当的值。 然后,您只需使用正确的值在格式字符串的初始段的副本上调用相应的printf()函数(因为您无法修改原始段)。 对于您的特殊情况,您可以做任何不同的事情。

能够将args参数传递给vprintf()以便处理收集类型等会很好,但我不认为它是可移植的(这无疑是一种麻烦)。 在将诸如args类的va_list值传递给在其上使用va_arg()的函数之后,在函数返回后,您无法在值上执行除va_end()之外的任何操作。


今年早些时候,我为POSIX增强格式字符串(支持n$表示法指定哪个参数指定特定值)编写了一个printf()样式格式字符串分析器。 我创建的标题包含(以及PFP_ErrnoPFP_StatusFWP_NoneFWP_Star ):

 typedef struct PrintFormat { const char *start; /* Pointer to % symbol */ const char *end; /* Pointer to conversion specifier */ PFP_Errno error; /* Conversion error number */ short width; /* Field width (FPW_None for none, FPW_Star for *) */ short precision; /* Field precision (FPW_None for none, FPW_Star for *) */ short conv_num; /* n of %n$ (0 for none) */ short width_num; /* n of *n$ for width (0 for none) */ short prec_num; /* n of *n$ for precision (0 for none) */ char flags[6]; /* [+-0# ] */ char modifier[3]; /* hh|h|l|ll|j|z|t|L */ char convspec; /* [diouxXfFeEgGAascp] */ } PrintFormat; /* ** print_format_parse() - isolate and parse next printf() conversion specification ** ** PrintFormat pf; ** PFP_Status rc; ** const char *format = "...%3$+-*2$.*1$llX..."; ** const char *start = format; ** while ((rc = print_format_parse(start, &pf)) == PFP_Found) ** { ** ...use filled in pf to identify format... ** start = pf.end + 1; ** } ** if (rc == PFP_Error) ** ...report error, possibly using print_format_error(pf.error)... */ extern PFP_Status print_format_parse(const char *src, PrintFormat *pf); extern const char *print_format_error(PFP_Errno err); extern PFP_Status print_format_create(PrintFormat *pf, char *buffer, size_t buflen); 

解析函数分析源并在结构中设置适当的信息。 create函数采用结构并创建相应的格式字符串。 请注意,示例中的转换说明符( %3$+-*2$.*1$llX )是有效的(但有点可疑); 它转换一个作为参数3传递的unsigned long long整数,其宽度由参数2指定,并且由参数1指定的精度。你可能可以有更长的格式,但只有几个字符没有重复,即使你使用了几十个总共有数百个参数。

没有简单,便携的方法来做到这一点; 要检查va_list ,您必须知道它包含的值的类型,并且唯一的方法是通过解析格式字符串。 实际上,你必须重新实现vprintf一部分。 (部分,因为您仍然可以将单独的格式说明符+转换值对发送到printf ,而不用担心如何拆分float 。)