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
退出函数集后,由于破坏局部变量i,指针p的值变得无效。程序具有未定义的行为。使用指针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 当编译器未进行优化时,在第一种情况下(即一行中的整个计算),它首先
p
的结果未定义,它也可能给您一个segfault或只是返回42。您得到结果背后的技术原因可能是:
insidei
被放置在堆栈上。值7存储在那里,并且Set
指向内存中的该位置。当您从p
返回时,值保留在内存中:堆栈未“销毁”,它只是重置的堆栈指针。Set
仍然指向此位置,该位置仍然包含“3”的整数表示形式p
- 在
内部,堆栈上的同一位置可重复用于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();
}