一些程序员认为在另一个函数内部定义一个函数称为“嵌套函数”。但是现实是它不是嵌套函数,它被视为词汇作用域。在C语言中,词法作用域无效,因为编译器无法达到/找到内部函数的正确内存位置。

c语言入门必背函数(CC编程笔记)(1)

C不支持嵌套函数,因为我们无法在C中的另一个函数内定义一个函数。我们可以在一个函数内声明一个函数,但它不是嵌套函数。

由于嵌套函数定义无法访问周围块的局部变量,因此它们只能访问包含模块的全局变量。这样做是为了不必在目录中查找全局变量。与C中一样,有两个嵌套作用域:本地和全局(除此之外,内置函数)。因此,嵌套函数只有有限的用途。如果尝试在C中使用嵌套函数,则将得到编译时错误。

c语言入门必背函数(CC编程笔记)(2)

输出:

编译时错误:未定义对“视图”的引用

GNU C编译器的扩展允许声明嵌套函数。在GCC扩展名下的嵌套函数的声明需要以auto关键字为前缀/开头。

c语言入门必背函数(CC编程笔记)(3)

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

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

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

c语言入门必背函数(CC编程笔记)(4)

其中offset就是容器函数中的变量,可以在嵌套函数中直接引用,这看起来似乎不难实现:通过sp offset即可轻松访问容器函数的栈变量,但还有一种情况必须要考虑,那就是嵌套函数不仅仅可以在容器函数中直接调用,还可能通过函数指针在其他函数中间接调用,这时活动栈帧布局跟容器函数就不一样了,通过sp offset访问到的不再是容器函数中的对应变量位置了,这样就会得到意想不到的结果。

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

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

另外如果你想更好的提升你的编程能力,学好C语言C 编程!弯道超车,快人一步!

编程学习书籍分享:

c语言入门必背函数(CC编程笔记)(5)

编程学习视频分享:

c语言入门必背函数(CC编程笔记)(6)

分享(源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

C语言C 编程学习交流圈子,点击下方【了解更多】获取更多学习资料帮助你学习成长哦~

,