栈的应用补充:
迷宫问题
二进制问题
递归问题
在传统的递归中,典型的模型是首先执行递归调用,然后获取递归调用的返回值并计算结果。以这种方式,在每次递归调用返回之前,您不会得到计算结果。传统地递归过程就是函数调用,涉及返回地址、函数参数、寄存器值等压栈(在x86-64上通常用寄存器保存函数参数),CTF-PWN的很多基础性漏洞EXP核心其实也是函数栈的问题。
传统递归的缺点:
- 效率低,占内存
- 如果递归链过长(可以理解为对应的树的深度大),可能会statck overflow(栈溢出)
尾递归,形式上函数尾部返回自身
// 连乘操作的尾递归,不需要消栈int factorial(int n){return n == 0 ? 1 : n * factorial(n - 1);// 无需返回factorial(n)}
//GCC开O1优化生成的汇编代码是通过函数调用,非尾递归的;factorial:.LFB22:.cfi_startprocpushq %rbx // push the old n, means n + 1.cfi_def_cfa_offset 16.cfi_offset 3, -16 // maybe update the frame pointer?movl %edi, %ebxmovl $1, %eaxtestl %edi, %edi // test if n == 0je .L2 // if is true, jumpt to .L2leal -1(%rbx), %edi // %edi = n - 1call factorialimull %ebx, %eax // result = n * factorial(n - 1).L2:popq %rbx // pop the old n.cfi_def_cfa_offset 8ret.cfi_endproc//O2优先级,则GCC会作尾递归优化:factorial:.LFB22:.cfi_startproctestl %edi, %edimovl $1, %eaxje .L2.p2align 4,,10.p2align 3.L3:imull %edi, %eaxsubl $1, %edijne .L3 // It's a loop.L2:repret.cfi_endproc
参考
后缀表达式 & 符号匹配问题
