C语言中Printf()函数的运行机制

2014-11-24 09:22:26 · 作者: · 浏览: 0

printf()是用来输出一个格式化的串的;它的参数个数是不确定的;可以有多一个;


但必需有一个;就是第一个格式串.这个不能缺.第一个参数要求是const char*


但你也可以使用char* ,只是你最好使用一个const char*;这样是安全的;


这一个涵数的第一个用法也是最简单的使用方法就是printf(str);


如:printf("hello world");


第二种使用方法是串中存在其他格式;


如: printf("this is a number %d",i);


%d告诉printf要把i格式成一个整型数据来输出;如果i==2;


那么输出是this is a number 2


就这二种方法;格式%输出还有很多种情况%f %c ....;但在这里我不想谈论这个格式问题;


因为书上说了很多...


在这里我要说的是printf是怎么使用参数的;如果有人格式化时候出现逻辑错误;为什么输出的是那样的结果; 【 Linux公社 www.Linuxidc.com 】


我要说的是结果为什么是那样而不是这样.也许这正是新手真正想了解的:


第一步,先了解printf是怎么传递参数的;printf()是通过把参数从右到左的顺序压栈的;


如printf("a=%d b=%d",i,j);会先压j然后压i然后压这个串"a=%d b=%d"的首地址


所以这个调用总共要压三个参数;


不管你要几个参数都好,第一个参数一定要是一个串的地址;这个地址是最后压栈的;


printf知道你传来几个参数吗


不知道!!!


它首先关心的是最后压进来的参数(就是"a=%d b=%d"这个串的首地址);


然后printf对这个串进行检查;如果发现存在%格式化要求.它就认为倒数第二个存在参数(不管是否真的存在)要以%所要求的


格式输出;如%c要以字符来输出一样;


如果你串中有这种格式,而你却没给传过去参数.情况会怎么样 如这样:printf("this is %d");


printf会认为你确实传过来了;尽管你真的没有传;它都会以第格式串的上面压有一个参数;


它会去取那个空间的数据出来按格式输出;此时候那个空间应该是属于上一级的涵数的栈空间;


所以输出多部分是随机的;鬼才知道哪里存放的是什么;


所以printf()是靠串的格式来判断参数的多少的;但如果错了;程序一般情况还是能很好的运行;


因为它只读栈不写;所以没有破坏性;


而且参数的清空责任是有调用他的涵数来负责的,所以栈总能平衡.


好了;该说说你的程序了;


你printf("the is a int %d"+i); 是吧 这样传了几个参数呢


一个!


这个参数是什么呢 是"the is a int %d"的首地址加上i的和;


printf是怎么看这个参数的呢 printf认为它是一个需要格式输出的串的首地址;


我们知道i=10;


所以当它把首地址加i就是加10后;地址就跑到N这个字母哪里了;


所以就从n那里开始输出;当它遇到%d的时候;


它就认为你还传来一个需要以%d格式输出的数;所以它就去串地址所压的地方的上面取参数;


当然这样只会取到起上一级的涵数的栈空间的数据;


如在你的程序中;我所说的上一级的涵数就是main()


所以就取上一级的栈空间里的东西;如i就是main()栈里的


MASTERRAY的实验是输出10;但我说这个10是偶然的;没有必然;就是随机的;它可以随编译器的不同而不同;随优化设置不同而不同;


如果你用VC6.0运行你就发现它不是10;但确定的是从nt处开始;只有一种情况才是10;那就是就在call printf前没有任何push操作;


这样栈里的i就能很靠近压在栈里的参数;只有靠近才能输出i;总之它只拿压参数之前所压的东西;PUSH 参数之前PUSH的是什么,;那就


是什么。。