对于以下代码,这就是我的理解: 对指针x的引用传递给函数f, val获取y的地址,这是一个局部变量。 那么为什么在退出函数f之后,x还可以呢?你应该被解除引用。 x等于5,两个printf都打印相同的地址。
void f (int ** val)
{
int y = 5 ;
*val = & y;
printf("%d\n", &y);
}
int _tmain(int argc, _TCHAR* argv[])
{
int * x ;
f(&x );
if ( *x == 5 )
printf("%d", x);
}
答案 0 :(得分:7)
Undefined Behaviour 可以访问您的程序不拥有的内存。
函数内部y
占用的内存空间在函数完成后不属于您的程序,但您可以访问它。
任何事情都可能发生。
最糟糕的事情是让程序按照您的预期行事。
当发生这种情况时,你相信做你做的事情是可以的。 不行。未定义的行为很糟糕。
此外,不保证在程序的不同运行中也会发生相同的未定义行为。它可以像您期望的那样工作,并在您向客户端(或您的老板)演示时崩溃。
( UB 的一些好表现是崩溃,或柠檬汁开始渗出USB端口)
任何事情都可能发生。
答案 1 :(得分:3)
x
指向f
内的局部变量,该变量在f
返回时不再有效。
编辑:你的帖子没有说清楚你期望会发生什么,但正如其他答案中所描述的更清楚,*x
指向你不拥有的记忆,并从{{1}读取是未定义的行为,所以所有的赌注都是关闭的。如果您尝试从*x
读取并且恰好为5,则可能是因为值5仍在堆栈中。在调用*x
后立即尝试向printf
插入一些调用,您可能会得到另一个结果。
答案 2 :(得分:2)
y
变量位于堆栈上。所以你将堆栈上的地址传递给x,它是一个有效的地址,但内容未定义。如果在调用printf
和检查f
之间添加另一个函数(如*x == 5
),则可能会得到不同的结果(因为堆栈已更改)。
答案 3 :(得分:1)
这是经典......
只要执行函数y
,变量f
才有效。一旦它返回,堆栈上y
占用的内存空间可用于其他任何内容。
答案 4 :(得分:1)
y
仅存在于f(int**val)
内,因为它是在此范围内声明的。f()
之外的地址没有明确的定义(或者我们喜欢):未定义的行为。
答案 5 :(得分:0)
因为y可能无效,但它的值仍在内存中。 如果你打电话给其他一些函数或者做一些其他的函数就会变得很讨厌。
答案 6 :(得分:0)
几乎每个人都已经说过,这是不明确的行为。打印正确值(5)的原因是因为您的程序没有重用该内存,尚未。等到你的程序在该地址放入其他内容,然后你会看到不正确的结果。