[英]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_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);
解析功能分析源並在結構中設置適當的信息。 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.