printf输出float和double类型数据的问题
以前都一直以为printf输出double类型使用的是%lf,今天才发现输出float和double使用的都是%f。这让我很是迷惑。因为printf是变参函数,参数的入栈和出栈都是由被调用者完成。printf识别各个参数完全是通过输出格式字符串中获取要输出的参数的类型。float和double分别占用4和8个字节的空间,当printf看到%f的时候如何知道这个数据是几个字节呢?难道float类型在入栈的时候也是自动按照double来如栈吗?
如果各位有知道其中原因的,还望不吝赐教。
[解决办法]
查MSDN得:
e double
E double
f double
g double
G double
所以,不是printf知道是什么类型,而是在输出时做了强制转换。
把float赋给double不会丢失精度一样。
[解决办法]
应该是将%f转换成double再入栈
[解决办法]
是因为使用了自动向上类型转换
[解决办法]
...
while ((ch = *format++) != _T('\0') && charsout >= 0) {
chclass = find_char_class(ch); /* find character class */
state = find_next_state(chclass, state); /* find next state */
/* execute code for each state */
switch (state) {
...
case ST_SIZE:
/* just read a size specifier, set the flags based on it */
switch (ch) {
#if !LONG_IS_INT
[解决办法]
!defined (_UNICODE)
case _T('l'):
flags
[解决办法]
= FL_LONG; /* 'l' => long int or wchar_t */
break;
#endif /* !LONG_IS_INT
[解决办法]
!defined (_UNICODE) */
...
case ST_TYPE:
switch (ch) {
...
case _T('E'):
case _T('G'):
capexp = 1; /* capitalize exponent */
ch += _T('a') - _T('A'); /* convert format char to lower */
/* DROP THROUGH */
case _T('e'):
case _T('f'):
case _T('g'): {
/* floating point conversion -- we call cfltcvt routines */
/* to do the work for us. */
flags
[解决办法]
= FL_SIGNED; /* floating point is signed conversion */
#if !LONGDOUBLE_IS_DOUBLE
/* do the conversion */
if (flags & FL_LONGDOUBLE) {
LONGDOUBLE tmp;
tmp=va_arg(argptr, LONGDOUBLE);
/* Note: assumes ch is in ASCII range */
_cldcvt(&tmp, text.sz, (char)ch, precision, capexp);
} else
#endif /* !LONGDOUBLE_IS_DOUBLE */
{
DOUBLE tmp;
tmp=va_arg(argptr, DOUBLE);
/* Note: assumes ch is in ASCII range */
_cfltcvt(&tmp,text.sz, (char)ch, precision, capexp);
}
...
}
break;
{
DOUBLE tmp;
tmp=va_arg(argptr, DOUBLE);
/* Note: assumes ch is in ASCII range */
_cfltcvt(&tmp,text.sz, (char)ch, precision, capexp);
}