C++ 指针引用的值不再存在时的冲突输出 #包括 #包括 int*p; 空集() { int i; i=7; p=&i; } int Use() { 双d; d=3.0; d+=*p; //如果我将上述3条语句替换为-->双d=3.0+*p;则输出为10,否则输出为某个随机值(随机内存位置的地址) //为什么会这样?不一样吗? 返回d; } void main() { clrsc(); Set(); cout

C++ 指针引用的值不再存在时的冲突输出 #包括 #包括 int*p; 空集() { int i; i=7; p=&i; } int Use() { 双d; d=3.0; d+=*p; //如果我将上述3条语句替换为-->双d=3.0+*p;则输出为10,否则输出为某个随机值(随机内存位置的地址) //为什么会这样?不一样吗? 返回d; } void main() { clrsc(); Set(); cout,c++,function,pointers,C++,Function,Pointers,退出函数集后,由于破坏局部变量i,指针p的值变得无效。程序具有未定义的行为。使用指针p的结果未定义,它也可能给您一个segfault或只是返回42。您得到结果背后的技术原因可能是: iinsideSet被放置在堆栈上。值7存储在那里,并且p指向内存中的该位置。当您从Set返回时,值保留在内存中:堆栈未“销毁”,它只是重置的堆栈指针。p仍然指向此位置,该位置仍然包含“3”的整数表示形式 在Use内部,堆栈上的同一位置可重复用于d 当编译器未进行优化时,在第一种情况下(即一行中的整个计算),它首先

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

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

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

  • Use
    内部,堆栈上的同一位置可重复用于
    d

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

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

这个例子说明了为什么返回指向局部变量的指针/引用是一件非常糟糕的事情:在编写函数
Set
时,您甚至可以编写某种单元测试,它们不会检测到错误。在软件投入生产之前,它可能会被忽略,并且必须执行一些真正关键的任务,并且导致测试失败n


这适用于所有类型的“未定义行为”,尤其是在“低级”语言(如C/C++)中。坏的是,“未定义”很可能意味着“完美地工作到为时已晚”…

你的键盘上有一个
标签吗?而且,没有合理的解释来解释这个不合理的问题。UB就是UB。我认为这个问题更多的是关于编译器/汇编级别上发生的事情,而不是关于正确的C用法。海报提到他理解,代码在某种意义上是无效的,因为它会引发未定义的错误ned Behavior。他只是想解释为什么会发生某些特定的行为。这不是一个坏问题,因为它有助于理解“未定义的行为”的含义(在具体的技术实现中)以及为什么它会导致难以发现的错误(因为它们可能不会首先发生).@H2CO3总会有一些解释…@MartinStettner,在这种情况下,就是“每个行为都是正确的”,因为你有UB。这就是我的观点。如果我被摧毁了,为什么双d=3.0+*p;会给出10?
#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();
}