0
#include<stdio.h>

int *fun();
int main()    
{
   int *ptr;
   ptr=fun();
   printf("%d",*ptr);
   printf("%d",*ptr);
}
int * fun()
{
   int k=4;//If auto then cannot print it two times.....stack will be changed
   return(&k);
}

O/P: 4
    -2

第一次调用 printf() 会打印正确的值。

在调用 fun() 之后立即调用任何函数(甚至 printf())。这次 printf( ) 打印一个垃圾值。为什么会发生这种情况?为什么我们在第一个打印语句本身期间没有得到垃圾值????

4

3 回答 3

1

这不是您可以依赖的行为;在不同的系统,甚至不同版本的编译器或不同的编译器开关上,它可能并且可能会有所不同。

鉴于此,可能发生的情况是:fun 返回一个指向它存储 k 的位置的指针。堆栈的那部分不再可靠,因为分配它的函数已经退出。尽管如此,还没有人写过它,所以 4 仍然是它写的地方。然后 main 准备调用 printf。为此,它获取第一个参数 *ptr。为此,它从位置 ptr 点加载,这是 k 的(前)地址,因此加载得到的是那里的 4。这 4 存储在要传递给 printf 的寄存器或堆栈位置中。然后存储格式字符串的地址“%d”以传递给 printf。然后调用 printf。此时,printf 使用了大量的堆栈,并在 k 以前的位置写入新数据。但是,作为参数传递的 4 是在一个安全的地方, printf 的参数应该是,所以 printf 打印它。然后 printf 返回。然后主程序准备再次调用 printf。这一次,当它从 ptr 指向的位置加载时,4 不再存在;这是在第一次调用 printf 时写入的一些值。因此,该值是传递给 printf 并且是打印的值。

永远不要编写使用这种行为的代码。它不可靠,也不是正确的代码。

于 2012-07-27T20:08:56.927 回答
1

为什么会让你感到惊讶?行为是未定义的,但观察你观察到的并没有什么不寻常的。

所有变量都存在于内存中的某个地方。当一个变量被正式销毁时(如函数退出时的局部变量),它曾经占用的内存仍然存在,并且很可能仍然保存最后写入的值。该内存现在正式免费,但它将继续保持最后一个值,直到其他代码将该内存用于其他目的并覆盖它。

这是你在实验中观察到的。即使变量k不再存在,指针ptr仍然指向它以前的位置。并且那个以前的位置仍然恰好持有 的最后一个值k,即4

第一个printf“成功”接收到该值的副本以进行打印。第一个printf实际上是重用旧内存位置并覆盖k. 所有进一步取消引用的尝试都ptr将表明它4不再存在,这就是为什么您的第二个printf打印其他内容的原因。

于 2012-07-27T21:08:57.957 回答
0

变量k是本地的fun(),意味着它会在函数返回时被销毁。这是一种非常糟糕的编码技术,总是会导致问题。

以及第一个printf返回正确值的原因:

首先,它可能会也可能不会返回值。事情是假设k写在堆栈内存的某个地方。第一次函数返回时 printf 可能会得到正确的值,因为这部分内存可能存在一段时间。但这不能保证。

于 2012-07-27T20:13:01.277 回答