悬浮指针的“可视化”

时间:2014-01-09 14:27:41

标签: c pointers visualization

在学习指针时,我尝试了指针声明/解除引用。

#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”的地址仍然是同样的。

2 个答案:

答案 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根本不可用。

答案 1 :(得分:1)

“call”是返回指向变量的指针吗?这里的问题是“a”不是静态分配的,而是在堆栈上。你现在可以返回它的地址(可能是也可能不是同一个地址,这取决于每次都在同一深度调用“call”),但是不能保证从你返回后该地址指向的地址是什么“呼叫”。你在通话期间放了一个3,当你到处查看那个地址的内容时,可能会被别的东西覆盖。