指针引用的值不再存在时输出冲突


#include<iostream.h>
#include<conio.h>
int *p;
void Set()
{
   int i;
   i=7;
   p=&i;
}
int Use()  
{
   double d;
   d=3.0;
   d+=*p;
//if i replace the above 3 statements with --> double d=3.0+*p; then output is 10          otherwise the output is some random value(address of random memory location)
//why is this happening? Isn't it the same? 
   return d;
}
void main()
{
   clrscr();
   Set();
   cout<<Use();
   getch();
}

我的问题如上面的评论所述。我想知道输出差异的确切原因。在上面的代码输出中是随机内存位置的一些地址,我知道这是因为 i 是 Set(( 的局部变量,但在第二种情况下它是如何可见的,即用双 d=3.0+*p 替换它;因为这样输出是 10( 7+3 ( 虽然 7 不应该可见?

使用指针 p 的结果是未定义的,它也可能给你一个段错误或只返回 42。您获得的结果背后的技术原因可能是:

  • Set内的i放在堆栈上。值 7 ist 存储在那里,p指向内存中的该位置。当你从Set返回时,值保留在内存中:堆栈没有被"销毁",它只是重置了堆栈指针。 p仍然指向此位置,该位置仍包含"3"的整数表示形式。

  • Use内部,堆栈上的相同位置被重用于d

  • 当编译器没有优化时,在第一种情况下(即一行中的整个计算(,它首先使用值 7(它仍然存在于内存中,p指向它(,进行计算,覆盖该值(因为您将其分配给位于同一位置d(并返回它。

  • 在第二种情况下,它首先用双精度值 3.0 覆盖该值,然后将前 4 个字节解释为整数值以计算 d+=*p 中的*p

这个案例说明了为什么返回对局部变量的指针/引用是如此糟糕:在编写函数Set时,您甚至可以编写某种单元测试,但它们不会检测到错误。它可能会被忽视,直到软件投入生产,并且必须执行一些非常关键的任务,然后就会失败。

这适用于所有类型的"未定义行为",特别是在C/C++等"低级"语言中。不好的是,"未定义"很可能意味着"完美地工作,直到为时已晚"......

退出函数后 设置指针 p 的值由于破坏局部变量 i 而变得无效。程序具有未定义的行为。

最新更新