变量的范围。内部工作基础

时间:2012-11-06 08:54:47

标签: c memory-management

这是关于变量假设范围的一个非常基本的问题。我有一个fiollowing代码:

int main()
{
    int *p;
    p=func();
    printf("%d",*p);
    return 0;
}

int *func()
{
   int i;
   i=5;
   return &i;
}

我的问题

  • i的范围已在func()中完成,但是,由于我将返回i的地址,我可以访问print中的main() 5吗?< / LI>
  • 如果没有,为什么?编译器是否在该地址空间中放置了一个垃圾值(我不认为这样做了。)
  • the scope of a variable is ended 实际上意味着什么?分配给i的内存是否在其范围结束时被释放?

5 个答案:

答案 0 :(得分:4)

变量的

范围是可以访问它的区域 变量的生命周期是保证变量存在的时间。

在你的情况下,i生命周期是在不超出它的功能范围内。这意味着i不能保证在函数之外存在。它不是必需的,并且未定义的行为可以访问函数之外的局部变量。

  

i的范围已在func()中完成,但由于我将返回i的地址,我将能够访问并打印5 main()

你可以,但它是未定义的行为。所以不要这样做。

  

如果没有,为什么?编译器是否在该地址空间中放置了一个垃圾值(我不认为这样做了)

编译器可以将它选择的任何内容放在该位置,一旦函数返回,地址位置就会包含 Indeterminate 值。

  

变量范围究竟意味着什么?分配给i的内存是否在其范围结束时被释放?

i是一个自动/局部变量,一旦声明它们的范围{}结束,所有自动变量都将被释放。因此名称自动。

答案 1 :(得分:2)

未定义行为在超出范围后访问变量。这意味着无法说出肯定会发生什么。在发布的代码中,可能会打印5,可能会打印其他一些值或者可能会出现其他一些行为(例如访问冲突)。

答案 2 :(得分:2)

示例中的行为未定义。你的printf可能会输出5,但这要归功于运气而不是好的设计。

在这种情况下,当变量的范围结束时,进一步的函数调用可以重用堆栈地址&i来改变p变量指向的值。

答案 3 :(得分:2)

不,访问超出范围的变量会导致未定义的行为。曾经回收过v变量的存储空间,因此您可能会覆盖其他可能导致崩溃或不可预测行为的内容。

答案 4 :(得分:2)

你的功能可能会打印5,但你永远不应该这样做。它是未定义的行为,因为您的程序不再拥有返回指针指向的位置(换句话说,您的程序不再拥有i)。

基本上每次调用函数时,都会向下推送堆栈指针以容纳新的堆栈帧。当函数调用结束时,堆栈指针会重新抬起。这意味着如果要调用不同的函数,它将与前一个函数调用重叠相同的堆栈空间。

为了更好地说明这一点,请考虑以下事项:

int main()
{
    int *p;
    p=func();
    printf("%d\n",*p);
    func2();
    printf("%d\n",*p);
    return 0;
}

int *func()
{
   int i;
   i=5;
   return &i;
}

void func2()
{
    int i = 1;
}

输出很可能是5 1.这是因为第二次调用将重用相同的堆栈空间。

(请注意,上面的代码段是可怕的 - 你永远不应该做那样的事情 - 它是未定义的行为,并且高度依赖于实现。)


直接回答您的问题:

  

i的范围是在func()中完成但是,因为我将返回i的地址,我能够在main()中访问和print5吗?

没有。你可以,但你不应该。这就是C的美丽。根据编译器/ OS /等,它可能输出5,或者它可能输出随机车库。

  

如果没有,为什么?编译器是否在该地址空间中放置了一个垃圾值(我不认为这样做了。)

重用用于局部变量的空间。答案的前半部分有希望说明这是如何工作的。 (好吧,通常的工作原理。)

  

变量范围究竟意味着什么?当范围结束时,分配给i的内存也被释放了吗?

Stack based memory allocation是幕后发生的事情。

相关问题