printf和强制转换float参数

Yak*_*kov 3 c printf casting

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

int ret = vprintf (format, args);
Run Code Online (Sandbox Code Playgroud)

args我得到的堆栈,我不知道到底是什么,压入堆栈。格式是一个字符串,我可以阅读。

在我必须打印浮点数之前,以上方法一直有效。当我打印浮动时,我得到一些奇怪的数字...

我检查了是否调用float fArg = *(reinterpret_cast<const float*>(args)-然后打印fArg正确的值(当args仅由一个实际参数组成时,我尝试了它)

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

Jon*_*ler 5

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

float f = va_arg(args, float);  /* BAD! */
Run Code Online (Sandbox Code Playgroud)

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

float f = va_arg(args, double);  /* OK */
Run Code Online (Sandbox Code Playgroud)

这可能是您的整个问题。


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

能够将args参数传递给vprintf()它,以便它处理收集类型等问题,这是很好的,但是我不认为这是可移植的(无疑是麻烦的)。将va_list值(例如)传递给args使用该值的函数之后va_arg(),您将无法va_end()对该函数返回后的值进行可靠的操作。


今年早些时候,我printf()为POSIX增强的格式字符串(支持n$表示指定哪个参数指定特定值的表示法)编写了一个-style格式字符串分析器。创建的头我包含(连同枚举的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);
Run Code Online (Sandbox Code Playgroud)

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