printf函数的一些理解

时间:2022-02-15 20:03:26
问题:

调用
printf("%.1f%s",0.0,"a");
的输出是
0.0a

而调用
printf("%.1f%s",0,"a");
的输出是
0.0@

第二个输出的字符并不是“a”(ASCII码97),而是“@”(ASCII码64),在VC 6下。

为什么?具体原因。

 

解答:
1,查看两句话的反汇编
1)    printf("%.1f,%s", 0.0,"a");
004113BE  mov         esi,esp 
004113C0  push        offset string "a" (41581Ch) 
004113C5  sub         esp,8 
004113C8  fldz 
//将0.0压入到st(0)中
004113CA  fstp        qword ptr [esp] 
//将st(0)中的内容存放到qword ptr [esp]指定的位置(4*4个字节=8个字节)
004113CD  push        offset string "%.1f,%s" (415800h) 
004113D2  call        dword ptr [__imp__printf (4182BCh)] 
2)    printf("%.1f,%s", 0,"a");
004113BE  mov         esi,esp 
004113C0  push        offset string "a" (41580Ch) 
004113C5  push        0    
004113C7  push        offset string "%.1f,%s" (415800h) 
004113CC  call        dword ptr [__imp__printf (4182BCh)] 
我们可以得知编译器把"0.0"解释成8个字节的类型,而把"0"解释成4个字节的类型,因此在对0.0和0入栈的过程中导致了栈内容的不一致,如下图所示,而printf的格式字符串%f是把参数解释成4个字节的类型,因此,它通过弹栈取出的只有4个字节,故此导致下一个参数(这里是字符串变量)的地址出现偏差,因而取出该地址下的内容也就不正确了,是未确定的。
printf函数的一些理解
2,顺便记录一下printf的实现
printf是个函数,其参数是valist类型的,也就是说参数是不固定的,它的实现是
*   Algorithm:
*       The format string is parsed by using a finite state automaton
*       based on the current state and the current character read from
*       the format string.  Thus, looping is on a per-character basis,
*       not a per conversion specifier basis.  Once the format specififying
*       character is read, output is performed.
一个有限自动机来解析格式字符串的。格式串之后就是格式中对应的参数。这些参数是通过一个va_arg的宏来获取的,根据类型的不同返回的值也就不同。 

做人--天青白日