C语言中Printf()函数的运行机制
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是怎么传递参数的;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的是什么,;那就
是什么。。