递归调用放在系统堆栈上,这就是我所读过的。但如果这是真的,为什么在下面的程序中我得到所有rec()调用的相同地址。他们不应该在堆栈上有连续的地址吗?
void rec(int n )
{
printf("%d -> %p\n",n,rec);
if( n ==0 )
return;
else
rec(n-1);
}
当我在main()代码中调用rec(5)时,它给出了如下输出,
5 -> 0x4004f4
4 -> 0x4004f4
3 -> 0x4004f4
2 -> 0x4004f4
1 -> 0x4004f4
0 -> 0x4004f4
抱歉,如果我的查询太基础了。但我无法提出任何解释,除非是由于某种编译器优化。但我不确定。也请告诉我任何可以帮助我在程序运行时查看程序内存(不是大小,但内容)的工具。
提前致谢!!!
更新:
我在每个电话中添加了一个局部变量i,我得到了我想看到的内容。
5 -> 0x4004f4 0x7fff507d376c
4 -> 0x4004f4 0x7fff507d373c
3 -> 0x4004f4 0x7fff507d370c
2 -> 0x4004f4 0x7fff507d36dc
1 -> 0x4004f4 0x7fff507d36ac
0 -> 0x4004f4 0x7fff507d367c
谢谢你@EVERYONE:)
答案 0 :(得分:3)
答案 1 :(得分:1)
不,函数的地址在内存中的某个地方是静态的。在递归调用期间,您在堆栈上推送的是返回地址和函数范围内的所有局部变量。 Here是一个很好的教程。
答案 2 :(得分:1)
在你的功能中,当你说:
printf("%d -> %p\n",n,rec);
您要求函数rec(int)
的代码地址。编译器只创建函数的一个副本,所以你看到了这个。没有办法(AFAIK)可以从标准C中访问堆栈中的哪个位置。
答案 3 :(得分:1)
rec
是函数,代码中只有一个rec,因此没有理由更改地址
答案 4 :(得分:1)
函数调用确实放在堆栈上,但它们不是函数本身,而是所谓的堆栈帧。它们包含参数,局部变量和返回地址(可能还有更多)。
但是,当您打印rec
的地址时,您不会获得当前堆栈帧的地址,而是获取该函数代码的地址。这总是相同的,因为代码本身不会改变。
当您打印局部变量的地址时,您可以看到这有效:
printf("%p -> %p\n", &n, rec);
示例输出:
0028fee0 -> 004016d9
0028fec0 -> 004016d9
0028fea0 -> 004016d9
0028fe80 -> 004016d9
0028fe60 -> 004016d9
0028fe40 -> 004016d9
请注意,虽然第二个指针保持不变(它是函数指针),但第一个指针每次都会更改,因为每个调用中都有一个不同的n
- 变量。