c语言中的函数嵌套

来源:互联网 发布:淘宝介入谁先举证 编辑:程序博客网 时间:2024/05/17 16:03

一 概要

C语言标准c89和c99中并不支持函数嵌套功能,它是GUN C的一个拓展,所以在gcc中是可以支持函数嵌套的,gcc对嵌套函数的说明如下:

https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html


二 实现

gcc主要通过Trampoline实现函数嵌套功能,那么什么是Trampoline呢?

Trampoline其实就是一段存在于栈上的可执行代码,它由运行时动态生成,通过运行栈上的这段代码跳转到真正的目的代码处。

至于函数嵌套为何要通过Trampoline去实现,这还得从嵌套函数的特点说起,因为它能够访问容器函数中的局部变量:

bar (int *array, int offset, int size){  int access (int *array, int index)    { return array[index + offset]; }  int i;  /*  */  for (i = 0; i < size; i++)    /*  */ access (array, i) /*  */}
其中offset就是容器函数中的变量,可以在嵌套函数中直接引用,这看起来似乎不难实现:通过sp+offset即可轻松访问容器函数的栈变量,但还有一种情况必须要考虑,那就是嵌套函数不仅仅可以在容器函数中直接调用,还可能通过函数指针在其他函数中间接调用,这时活动栈帧布局跟容器函数就不一样了,通过sp+offset访问到的不再是容器函数中的对应变量位置了,这样就会得到意想不到的结果。

Trampoline可以有效的避免这种情况,因为Trampoline存在于容器函数的栈上,相对于要访问的容器函数的变量相对位置是固定的,所以不管怎么调用嵌套函数,执行的都是栈上的Trampoline,这样访问到的容器函数的变量位置总是正确的。不过这要求在嵌套函数调用时容器函数不能退出,否则栈上的Trampoline可能会被覆盖,同样会得到意想不到的结果。


三 优缺点

优点:函数调用时不用传递大量的参数;

缺点:代码移植性差,因为只有gcc支持,另外这要求栈是可执行的,不满足安全需求;


四 补充说明

如果嵌套函数中不引用容器函数中的任何变量,那么嵌套函数会被提升为普通函数,通过上面原理的分析,这点应该很好理解。


原创粉丝点击