【发布时间】:2021-09-14 20:22:23
【问题描述】:
#include <stdio.h>
int main()
{
int *ptr;
{
int x = 2;
ptr = &x;
}
printf("%x %d", ptr, *ptr);
return 0;
}
输出:x的地址,x的值。
这里,ptr 应该是一个悬空指针,对吧?但是,它仍然存储x 的地址。 即使删除了那个块,它怎么仍然指向x 的值?
#include <stdio.h>
int * func (int n)
{
int temp;
int *ptr = &temp;
temp = n * n;
return ptr;
}
int main()
{
int n = 4;
int *p = func(4);
printf("%x, %d", p, *p);
return 0;
}
输出:临时地址,16
在这个程序中,数据变量temp和它的指针变量ptr是在单独的函数中创建的。 为什么会产生正确的结果?
#include <stdio.h>
int * func (int n)
{
int temp;
int *ptr = &temp;
temp = n * n;
for (int i = 0; i < 10; i++)
printf("%d ", *ptr);
return ptr;
}
int main()
{
int n = 4;
int *p = func(4);
printf("\n%x, %d", p, *p);
for (int i = 0; i < 10; i++)
printf("%d ", *ptr);
*p = 12;
printf("%d\n", *p);
printf("%d\n", *p);
return 0;
}
输出:16 16 16 16 16 16 16 16 16 16
临时地址,1
16 16 16 16 16 16 16 16 16 16
12
12
除了for循环之外,上面的程序与第二个程序类似。在
main() 函数,它每次都给出正确的输出。即使我尝试将其更改为*p = 10,无论我打印多少次,它仍然会给出正确的输出。
但是在第二个程序中,由于未定义的行为,它只给出了一次正确的输出。它在第一个 printf 之后给出垃圾值。
但是在第三个程序中,它如何仍然每次都给出正确的输出?
我的问题是:
- 指针变量指向一个超出范围的局部变量,但仍会打印正确的输出,并且可以通过更改指针变量的值来访问它。为什么会这样?
- 与在 increment() 中创建的 temp 一样,ptr 也是在本地创建的。为什么它始终正确打印值而没有任何警告或错误?如果没有for循环,打印一次后也会报错。为什么会这样?
当我通过 temp 时,我收到警告和分段错误错误。但是为什么 ptr 是一个局部变量,可以正确打印值呢? - 在第一个程序中,多次打印 *ptr 后,它给出了正确的输出,我能够更改 *ptr = 1;在第一个 printf 之后。为什么即使变量超出范围,我也可以访问 ptr?
谢谢大家的回答。我现在从你所有的答案中都明白了。非常感谢。
【问题讨论】:
-
您正在引入未定义的行为
-
澄清@INDHUJA G 是这里的新海报,对C 来说可能相当新:未定义的行为意味着您的代码可能 可以工作,但可能不行。如果我们确实知道,那将是定义的行为。最好完全避免这种情况。
-
@Chris 和 Daniel。谢谢您的回答。它应该只给出未定义的行为。但是在我现在添加的第一个和第三个程序中,看起来像是定义的行为。这怎么可能?
标签: c dangling-pointer