c语言的内联函数如何输出 c语言的内联函数如何输出字符串

内联函数一般函数是编译时在内存中为它单独开辟一段空间的,它的“首地址”叫入口地址,函数体的代码都在里面 。另外一些形参和局部变量建立在一个叫“栈”的内存区 。栈的特性是先进后出 。
当程序运行到调用函数的地方,比如main函数中有一处函数调用a=printf(…),首先把main里面当前这段代码的物理地址保存起来,放到为printf()准备的栈里面去 , 叫做“函数调用现场保护” 。然后系统找到内存中printf()的入口地址,把实参的值按顺序传进来一一放到指定的位置上(形参的排列是有一定规律的) 。此后系统就离开main , 而开始去执行printf()去啦,也就是c语言的内联函数如何输出你说的“控制转移” 。
当printf()函数执行完,返回的时候开始把栈里面的内容依次取出来,别忘c语言的内联函数如何输出了他是先进后出的 , 也就是说最后取到原来的那个物理地址,于是系统又回到main的那个地方,然后把最近取出来的另一个变量的值送回到main的位置,比如这里由a接收 。同时把为printf()建立的栈销毁掉,printf()的那些形参和局部变量就统统寿终正寝了 。一个函数最多只能返回一个值,因为更早取出来的值都被抛弃掉啦 。
这种函数调用,因为要建栈、保护调用现场,转移物理地址 , 执行完了后还要再出栈、返回地址、返回局部变量值 , 挺耗时间的 。
补充:程序运行期间所有函数的栈是使用一段空间的 , 用"栈顶"和"栈底"为每个函数标记自己的栈 。新进栈的数据都放在栈顶 , 出栈的也是从栈顶开始出 。而当栈顶和栈底重合,这个栈差不多可以销毁它了(把栈顶和栈底标记改掉,没法找到它了 , 也就算销毁了),不过我在数据结构里面和汇编学的栈略有不同 。
今天看了一下VC++6.0编译出来的汇编码,它编译出来的程序大致是这样运行的:
调用一个普通的函数时,系统会把原来为main()所建栈的栈底地址进到栈里,以便返回时恢复main()的栈 , 接着把调用函数的实参进到栈里,把当前正在运行位置的物理地址(代码区的)也进到栈里,然后转到被调用函数的入口地址 。这时的栈还暂时属于main()的 。但马上会把这个栈顶提升为栈底(新栈底正好是刚才存放main栈顶地址的那个内存单元),新的栈只能向上发展,就把原来属于main的栈给屏蔽掉了 。关于实参和形参结合的过程,我认为前面实参的进栈就是了,实参在栈中所占的内存单元就是形参的地址,函数中需要操作形参就直接去栈里面找到它们 。
【c语言的内联函数如何输出 c语言的内联函数如何输出字符串】(PS:个别地方和我接触过的“标准”上说的有些矛盾,尤其是形参在栈底下面,是VC++的编译器对程序作了优化,减少了不必要的空间开销吗?也可能是我对栈的定义理解不是很准确 , 请见谅 。)
当函数全部语句执行完要返回时,严格遵循相反的步骤,把栈顶调回栈底,再向下把刚才保存的那个main的栈底地址取出来恢复为栈底,这时候栈的形态已经恢复为原来main的了,然后栈顶继续下降,就把调用现场的物理地址也取出来了,根据这个地址,流程回到了main中发生本次调用的地方(位于代码区) 。如果return语句返回的是一个数而不是变量名字,则这个数据不保存在内存中,而是保存在CPU的寄存器里面 。系统去指定的位置把返回值取出来送给左侧接受它的变量 , 然后把栈顶恢复到函数调用前的位置 , 继续向后运行 。
关于static关键字,它修饰变量的时候,系统会把这些变量放到内存中的静态存储区,而不是栈区 。静态存储区的单元一旦分配了,在程序结束前就不会被释放 , 也就谈不上再重新分配给其他的变量了 。但是楼主说的用来修饰函数,我感觉在VC++6.0下好像没有引起任何变化 。严格说来被调用函数结束后它在栈中的数据还继续存在着,但是系统不再访问它们了,其实我觉得也可以访问,但是编译器不肯去为我们做而已 。而且如果后面再发生一次函数调用,新的栈会紧挨着main生长,原来留下的那些数据就给覆盖掉了 。

推荐阅读