void first(){
int x;
int *p;
p= &x;
scanf("%d",p);
printf("The value in x or *p is: %d\n",x);
}
void second(){
int x;
int *ptr;
scanf("%d",&x);
printf("The value in *ptr is: %d\n",*ptr);
}
int main(){
first();
second();
}
在上面的代码中,second()
函数是未命中行为。我为x
变量赋予了什么值,该值已分配给*ptr
以及x。为什么呢?
答案 0 :(得分:6)
您没有为p
分配一个值,因此它仍然未初始化。试图取消引用该指针调用undefined behavior。
给p
一个值,你就会得到你期望的结果:
int *p = &x;
您的代码仍在打印正确值的事实是该未定义行为的一部分。未定义行为可以表现出来的方式之一是代码似乎正常工作,但是看似无关的更改会导致代码中断。
在这种特殊情况下,函数first
和second
分别定义了相同类型和相同顺序的2个局部变量。在对first
的调用完成后,包含该函数的x
和p
值的内存仍包含这些值,但还没有其他函数调用来覆盖它们。
然后在second
之后立即致电first
。 x
中的变量ptr
和second
最终在x
中使用与p
和first
相同的内存。由于ptr
未初始化,因此它仍然包含旧值,该值首先是x
的地址,恰好与x
中second
的地址相同
同样,这是未定义的行为,因此您无法始终依赖于这种情况。如果您将另一个变量添加到first
或在first
和second
之间调用另一个函数,则会修改first
以前使用的堆栈内存。然后,内存将包含一些其他值,您可能会打印垃圾值或核心转储。
如果使用不同的编译器或不同的编译器选项编译,相同的代码可能会给出不同的结果。例如,另一个编译器可能选择将每个函数中的变量以不同的顺序放在堆栈上,或者它可以决定在函数返回后将函数使用的堆栈清零。
答案 1 :(得分:0)
int *p=&x;
x的地址存储在p中。
printf("%d",*p);
由于p的地址为x,* p基本上意味着您将前往p指定的位置并拾取该项,即x的值。