#include <stdio.h>
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
}
void foo(int **const p)
{
int j = 11;
*p = &j;
printf("%d ", **p);
}上面的code打印:
11 11 Undefined-value为什么第三次打印未定义的值?为什么它最后不打印11?
发布于 2018-07-23 18:52:02
在foo内部,将*p (与main中的p相同)设置为局部变量的地址。当foo返回时,该变量将超出作用域,因此该地址不会指向任何有意义的位置。
返回局部变量的地址,然后取消引用该地址调用未定义行为。
至于可能发生的事情,当您在从*p返回后第一次读取foo时,由于没有调用其他函数,j驻留在堆栈上的地址还没有被重用。然后调用printf时,该地址确实会在printf的堆栈帧中被重用。然后,下一次读取*p时,它将包含放在那里的最后一个函数调用。
然而,要重申的是,这是未定义的行为,因此不能依赖于这种情况的发生。使用不同的编译器,甚至使用具有不同优化设置的同一编译器进行编译,可以更改未定义的行为如何显示自身。
作为一个未定义行为的示例,在使用-O0编译gcc时,我得到了以下输出:
11 11 11 使用-O1:
11 11 0使用-O2:
11 0 0使用-O3:
11 0 0注意,在一种情况下,我们得到了“预期的”输出,而在另一种情况下,我们没有得到,而且以不同的方式。
您可以通过将j定义为static或文件作用域(即函数外部)来避免此问题,在这种情况下,变量的生存期为完整程序的生存期,因此其地址始终有效。
发布于 2018-07-23 18:58:09
试试这个(不要将int j定义为局部变量):
#include <stdio.h>
void foo(int **const p);
int j = 11; // define int j outside of the function as public
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
}
void foo(int **const p)
{
*p = &j;
printf("%d ", **p);
}产出将是:
11 11 11当您在int j = 11;中定义void foo(int **const p)时,这些步骤如下:
*p取j地址**p将是11和foo函数的返回。现在因为int j;是本地的,所以j内存会在foo调用之后被销毁!
**p指向一个未定义的内容,在这种状态下,您将得到Undefined-value输出。
https://stackoverflow.com/questions/51485315
复制相似问题