69,369
社区成员
发帖
与我相关
我的任务
分享
...
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;
以上是printf实现的主要代码,其中须要说明的几个宏:
1.LONG_IS_INT:printf实现代码中始终定义为1;
2.LONGDOUBLE_IS_DOUBLE:在定义了_WIN32宏的情况下,被定义为1;在定义了_M_MPPC情况下,被定义为1;在定义了_M_M68K情况下,被定义为0;_WIN32、_M_MPPC与_M_M68K为Microsoft C++预先定义的,编译WIN32程序中是定义的_WIN32,因此LONGDOUBLE_IS_DOUBLE被定义为1;
3.DOUBLE:被定义为double。
这样,上面的代码就好看了,主要的是:
{
DOUBLE tmp;
tmp=va_arg(argptr, DOUBLE);
/* Note: assumes ch is in ASCII range */
_cfltcvt(&tmp,text.sz, (char)ch, precision, capexp);
}
因此"%f"也是按double读取的8字节,若实参为float,编译时会自动转换为double的。