作为我程序的一部分,我使用:
int ret = vprintf (format, args);
args
我进入堆栈,但我不知道堆栈上实际压入的是什么。
格式是字符串,我可以读取。
上述方法一直有效,直到我必须打印 float 。当我打印 float 时,我得到一些奇怪的数字......
我检查过如果我调用 float fArg = *(reinterpret_cast<const float*>(args)
- 然后打印 fArg
打印出正确的值(我在 args 仅由一个实际参数组成时尝试过)
所以我可能需要对 "%...f"
进行特殊处理子格式 - 应转换相应的(子)参数
浮。 (...
符号表示可以在 f
之前添加精度、宽度等)
我该如何实现?
最佳答案
请注意,对于可变长度参数列表,所有 float
值都被提升为(并作为)double
值。你不能可靠地使用:
float f = va_arg(args, float); /* BAD! */
因为该语言从不将浮点值放在堆栈上。你必须写:
float f = va_arg(args, double); /* OK */
这可能是您的全部问题。
如果没有,您可能需要扫描格式字符串,隔离格式说明符,并实现核心 printf()
代码的重要部分。对于每个说明符,您可以从 args
中收集适当的值。然后,您只需使用正确的值对格式字符串的初始段(因为您无法修改原始段)的副本调用适当的 printf()
函数。对于你的特殊情况,你可以做任何你需要做的不同的事情。
如果能够将 args
参数传递给 vprintf()
就好了,这样它就可以处理收集类型等问题,但我认为这不是便携(这无疑是一件麻烦事)。在将 va_list
值(例如 args
)传递给使用 va_arg()
的函数后,除了va_end()
函数返回后的值。
今年早些时候,我为 POSIX 增强格式字符串编写了一个 printf()
风格的格式字符串分析器(它支持 n$
符号来指定哪个参数指定一个特定的值)。我创建的 header 包含(以及 PFP_Errno
、PFP_Status
、FWP_None
和 FWP_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);
parse 函数分析源代码并在结构中设置适当的信息。 create 函数接受一个结构并创建相应的格式字符串。请注意示例中的转换说明符 (%3$+-*2$.*1$llX
) 是有效的(但有点可疑);它转换作为参数 3 传递的 unsigned long long
整数,宽度由参数 2 指定,精度由参数 1 指定。您可能有更长的格式,但只有几个字符没有重复,即使您总共使用了数十或数百个参数。
关于c - printf 和转换 float 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8114834/