#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();
}
我的问题就像上面的评论中提到的那样。我想知道输出差异的确切原因。在上面的代码输出是随机存储器位置的一些地址,我明白这是因为我是一个局部变量Set()但是在第二种情况下它是如何可见的,即将它替换为double d = 3.0 + * p;因为那时输出是10(7 + 3),虽然7应该不可见?
答案 0 :(得分:1)
使用指针p
的结果是未定义的,它也可能会给你一个段错误或只返回42.你得到的结果背后的技术原因可能是:
i
内的Set
被放置在堆栈中。值7存储在那里,p
指向内存中的该位置。从Set
返回时,值仍保留在内存中:堆栈未被“销毁”,它只是重置的堆栈指针。 p
仍指向此位置,该位置仍包含“3”的整数表示。
在Use
内,堆栈中的相同位置将重复用于d
。
当编译器没有优化时,在第一种情况下(即一行中的整个计算),它首先使用值7(它仍然存在于内存中,p
指向它) ,计算,覆盖值(因为你将它分配给位于同一位置的d
并返回它。
在第二种情况下, first 用double值3.0覆盖该值,然后将前4个字节解释为整数值,用于评估{{1}中的*p
}}
这个案例说明了返回指向局部变量的指针/引用是如此糟糕:在编写函数d+=*p
时,您甚至可以编写某种单元测试,但它们不会检测到错误。它可能会在软件投入生产之前被忽视,并且必须执行一些非常关键的任务,然后才会失败。
这适用于所有“未定义行为”的kindes,特别是在C / C ++等“低级”语言中。糟糕的是,“未定义”可能意味着“完全正常工作,直到为时已晚”......
答案 1 :(得分:0)
退出函数设置后,由于销毁局部变量i,指针p的值变为无效。该程序有不确定的行为。