可能重复:
Can a local variable's memory be accessed outside its scope?
第二个printf
有什么问题?
#include<stdio.h>
int* fun() {
int a =10;
return &a;
}
int main() {
int *a;
a = fun();
printf("%d",*a);
printf("%d",*a);
return 0;
}
我已经返回了局部变量的地址并将其传递给printf
。它第一次正确打印为“10”,但第二次显示垃圾值。
如果最初a
是指向10
地址的悬空指针,为什么不是第二次?
任何人都能解释一下吗?
我甚至在第一次调用printf
之前尝试调用其他函数,但我仍然得到相同的输出。
在BeniBela的回答之后我试了这个......
#include<stdio.h>
int* fun()
{
int a =10;
return &a;
}
void fun2(int d)
{
int a,b,c;
}
int main()
{
int *a,b;
a = fun();
fun2(5);
printf("%d",*a);
printf("%d",*a);
return 0;
}
仍然是相同的输出.. :(
答案 0 :(得分:9)
printf
没有问题,您的代码有未定义的行为。
您返回函数本地变量的地址,变量的 生命周期 仅限于范围({
,}
)函数,一旦函数的范围结束,变量就越长。标准不再需要变量存在。
所以你的指针引用了一些不存在的东西(虽然它可能)。简单地说,它是未定义的行为,你是编译器的怜悯,它可能会向您显示任何行为并且不提供相同的解释。
答案 1 :(得分:3)
实际发生的是:
所有局部变量都存储在堆栈中。
在调用fun之前,堆栈只包含*变量main,如:|int *a = undefined||
当调用fun时,fun的参数(即none),main的地址和fun的局部变量被添加到堆栈中:|int *a = undefined| return to main | int a = 10 ||
(还有帧指针但是没关系)
乐趣返回后,堆栈为|int *a = 2nd next stack var|| return to main | int a = 10 |
。最后2个堆栈变量无效,但它们仍然存在。
当第一个printf被调用printf的参数时(按逆序* a然后是“%d”),在* a之后再次添加printf的返回地址和局部变量并覆盖旧值:
它首先变为|int *a = 2nd next stack var| int a = 10 || int
a = 10 |
然后|int *a = 2nd next stack var| int a = 10 | "%d" |
然后|int *a = 2nd next stack var| int a = 10 | "%d" | return to
main ||
最后|int *a = 2nd next stack var| int a = 10 |
"%d" | return to main | local vars of printf ||
[编辑:]
fun2不会覆盖堆栈上的10,因为gcc会在堆栈上保留空容器,其中放置了被调用函数的参数。所以它不是我上面写的|int *a = 2nd next stack var| return to main | int a = 10 |
,而更像是|int *a = 4th next stack var | empty | empty | return to main | int a = 10 |
当调用fun2时,它变为|int *a = 4th next stack var | empty | 5 | return to main | int a = 10 |
,而10仍未被覆盖。
函数中的int *a,b,c
无关紧要,因为它们没有赋值。
使用gdb,您可以查看实际堆栈(它向后增长):
开心之前:
0xffffd454: 0x080496f0 0xffffd488 0x080484eb 0x00000001
noise (framepointer) address noise/empty bin
in main
有趣之后,在fun2及其论点之前:
0xffffd454: 0x0000000a 0xffffd488 0x08048441 0x00000001
a (framepointer) address noise/empty bin
in main
在fun2之后:
0xffffd454: 0x0000000a 0xffffd488 0x08048451 0x00000005
a (framepointer) address argument
in main for fun2
答案 2 :(得分:1)
编译时注意警告:
yourfile.c: In function ‘fun’:
yourfile.c:6:14: warning: function returns address of local variable [enabled by default]
这是范围问题,变量“a”在“fun”函数中有一个本地scope。当您尝试从main(在其范围之外)访问该局部变量的地址时,它的含义不再有效。 如果你想解决这个问题,你可以将变量设为全局变量(但是更改名称!)然后你会看到代码按预期工作:
int b;
int* fun()
{
b = 10;
return &b;
}
int main()
{
int *a;
a = fun();
printf("%d",*a);
printf("%d",*a);
getc(stdin);
return 0;
}
输出:
> 1010
答案 3 :(得分:0)
返回在函数内创建的对象的地址,因此在函数终止后可能不再有效。改为创建一个指针!