簡體   English   中英

printf和強制轉換float參數

[英]printf and casting float arguments

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

int ret = vprintf (format, args);

我進入堆棧的args ,但我不知道實際將什么壓入堆棧。 格式是一個字符串,我可以閱讀。

在我必須打印浮點數之前,以上方法一直有效。 當我打印浮動時,我得到一些奇怪的數字...

我檢查是否如果我調用float fArg = *(reinterpret_cast<const float*>(args) -然后打印fArg ,則會打印正確的值(當args僅由一個實際參數組成時,我嘗試了它)

因此,可能我需要對"%...f"子格式進行特殊處理-應將相應的(sub)參數轉換為float。 ...表示可以在f之前添加精度,寬度等)。如何實現?

請注意,對於可變長度參數列表,所有float值都將提升為(並作為double float值傳遞)。 您不能可靠地使用:

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指定。您可能具有更長的格式,但是只有幾個字符沒有重復,即使您使用tens也是如此。或總共數百個參數。

沒有簡單,可移植的方式可以做到這一點。 要檢查va_list ,您必須知道它擁有什么類型的值,唯一的知道方法是解析格式字符串。 實際上,您必須重新實現vprintf一部分。 (部分,因為您仍然可以將單獨的格式說明符+強制轉換值對發送給printf ,而不用擔心如何分拆float 。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM