1

可能重复:
可以在其范围之外访问局部变量的内存吗?

第二个有什么问题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我什至尝试在第一次调用之前调用其他函数,但我仍然得到相同的输出。

在贝尼贝拉的回答之后,我尝试了这个..

#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;
}

仍然是相同的输出..:(

4

4 回答 4

9

没有问题printf,您的代码具有未定义的行为
您返回函数局部变量的地址,变量的生命周期仅限于函数的作用域({}),一旦函数作用域结束,变量的存在时间更长。标准不需要变量不再存在。

所以你的指针指的是不存在的东西(尽管它可能)。简单地说,它是未定义的行为,你受编译器的支配,它可能会向你展示任何行为并且不提供相同的解释。

于 2012-09-06T12:14:56.357 回答
3

实际发生的是:

所有局部变量都存储在堆栈中。

  1. 在调用 fun 之前,堆栈只包含 main 的 *a 变量,如:|int *a = undefined||

  2. 当 fun 被调用时,fun 的参数(即没有)、main 的地址和 fun 的局部变量都被添加到堆栈中:(|int *a = undefined| return to main | int a = 10 || 还有帧指针但没关系)

  3. fun 返回后,堆栈为|int *a = 2nd next stack var|| return to main | int a = 10 |. 最后 2 个堆栈变量无效,但它们仍然存在。

  4. 当第一个 printf 被调用 printf 的参数时(以相反的顺序 *a then" %d"),在 *a 之后再次添加 printf 的返回地址和局部变量并覆盖旧值:
    它首先变为 |int *a = 2nd next stack var| int a = 10 || int a = 10 |
    then |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 ||

  5. 当第二个 printf 被调用时,*a 仍然指向第二个 bin,但是那个 bin 现在包含“%d”,它将显示为一个奇怪的数字

[编辑:]

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

在 fun 之后,在 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
于 2012-09-06T12:32:50.257 回答
1

编译时注意警告:

yourfile.c: In function ‘fun’:
yourfile.c:6:14: warning: function returns address of local variable [enabled by default]

这是一个范围问题,变量“a”在“fun”函数中具有局部范围。这意味着当您尝试从 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
于 2012-09-06T12:20:19.797 回答
0

您返回在函数内创建的对象的地址,因此在函数终止后可能不再有效。而是创建一个指针!

于 2012-09-06T12:15:30.557 回答