2014-01-09 30 views
2

学习指针时,我尝试了指针声明/取消指定。悬挂指针的“可视化”

#include <stdio.h> 
#include <stdlib.h> 
#include <Windows.h> 

int *call() { 

int a = 3; 

return &a; 
} 

int main() { 
    printf("call* is: %d\n", *call()); 
    printf("call is: %p\n", call()); 
    Sleep(2000); 

    printf("call* is: %d\n", *call()); 
    printf("call is: %p\n", call()); 
    Sleep(2000); 

    printf("call* is: %d\n", *call()); 
    printf("call is: %p\n", call()); 
    return 0; 
} 

所以“显然”“a”是一个局部变量。 但我的问题是, 当我读出“a”的地址时,它始终是相同的地址。 这是为什么?

PS:我在后台运行一个素数计算器来填充尽可能多的内存,并且我在“睡眠”中放置了程序等待,但仍然是“a”的地址是总是一样。

+1

程序中没有其他线程;你怎么能在后台运行任何东西?您的电冰箱是否也在后台运行? –

+4

好的:)我希望你有乐趣。 但是,你能告诉我如何“看”/“可视化”的地址“一”是不恒定的? – BZAD

+0

几乎所有的假设都是错误的,没有任何意义。首先请查找“未定义的行为”。然后,如果你仍然决定这个职业,那么去看看生成的机器代码,看看发生了什么。 –

回答

3

a位于当前线程的堆栈:每个功能call()运行时,它“分配” 4个字节的堆栈上股票a,返回地址,然后“释放”的空间,它使用的堆栈(它实际上没有分配/释放任何东西,只是抵消了堆栈指针)。

因此,如果你连续多次调用它,函数输入的堆栈状态将完全相同,所以堆栈上的实际地址a每次都是一样的(请注意,这个地址只要您退出该功能就无效)。

你应该这样做

int * call2(){ 
    int a = 0; 
    int *b = call(); 
    printf("%d",a); 
    return b; 
} 

然后

int *a = call(); 
int *b = call2(); 

你会看到ab会有所不同(的printf在那里,以确保编译器不会优化任何东西)

由于堆栈对当前线程是本地的(不受其他进程/线程影响),因此您的素数计算器和Sleep根本没有用处。

+0

非常感谢您的努力! 我正在慢慢获得力学的线索。 – BZAD

+0

欢迎您。请务必阅读http://en.wikipedia.org/wiki/Call_stack查看详细信息。这**将帮助你更好地理解正在发生的事情。一旦您对任何答案感到满意,请确保通过单击复选标记将其标记为已接受。 – Olotiar

+0

我必须再次感谢你,因为在另一个例子中,我可以检查,当我使用你的代码检查地址时,给定的解决方案必定是错误的。 – BZAD

1

“call”是要返回一个指向变量的指针吗?这里的问题是“a”不是静态分配的,而是在堆栈上。你现在可以返回它的地址(这可能是也可能不是相同的地址,这取决于每次调用“调用”时是否在相同的深度),但是不能保证你返回的地址指向的是什么“呼叫”。在通话过程中,您会在其中放入一个3,并且在您查看该地址的内容时可能会被其他内容覆盖。

+0

谢谢,在我的脑海里,我有一些建议可以解决这个问题。 – BZAD