在/prog/上找到了这个。我实际上用GDB处理了它,是的,它确实是一个递归。但是这是怎么发生的呢?
// This works on 32-bit x86 Linux with gcc as long as you don't enable optimization.
#include <stdio.h>
#include <stdlib.h>
static void factorial(int in, int *out)
{
*(&in-1)-=5-5*(1/in);
*out*=in--;
}
int main(int argc, char **argv)
{
int result=1;
int number=0;
if (argc!=2)
exit(1);
number=atoi(argv[1]);
if (number<1)
exit(2);
factorial(number, &result);
printf("%d! = %d\n", number, result);
return 0;
}
$ ./factorial 3
3! = 6
$ ./factorial 5
5! = 120
发布于 2011-06-16 18:52:14
甜。;)
这是非常不可移植的代码,只能在x86上运行。它所做的是更改堆栈上的返回地址,以便如果为in>1
,函数不会返回到call
指令后面的指令,而是返回到call指令本身。x86上的调用指令是5个字节(一个操作码加上调用目的地的4字节地址),因此需要从返回地址中减去5个字节。
这
*(&in-1)-=5-5*(1/in);
只是一种模糊的说法
if(in>1)
*(&in-1)-=5;
&in-1
是返回地址驻留在堆栈中的位置。
发布于 2011-06-16 18:50:09
它破坏了堆栈上的返回地址,导致了递归的发生。
*(&in-1)-=5-5*(1/in);
&in-1
可能是推送的返回地址。剩下的都是令人不快的魔法。
https://stackoverflow.com/questions/6370544
复制相似问题