【问题标题】:when are block scope variables allocated何时分配块范围变量
【发布时间】:2013-11-10 14:26:53
【问题描述】:

如果我有一个 c 函数

int foo(int input)
{
    int x = 5;
    if( input == 0 ){
        int y = 6;
    } else {
        int z = 7;
    }
}

我知道当我们进入函数时堆栈指针会被调整,这为int x 语句腾出空间。而且我知道yz 只存在于它们各自块的范围内。但是何时以及如何为他们分配空间?

【问题讨论】:

  • AFAIK 编译器可以选择自己的分配策略,只要它确保变量仅在逻辑范围内应该在范围内。不要认为规范规定了具体的分配。
  • 那些变量?到优化器完成时,永远不会
  • 我知道它们会被优化掉。为了简洁起见,我没有输入“......并做某事......”我会在以后的问题中提出。

标签: c++ c scope stack


【解决方案1】:

这取决于编译器,只要空间至少在变量的生命周期内持续。

通常,函数中所有自动变量的空间在函数开始时在堆栈上分配,并在函数返回时释放。如果某些变量不需要有地址,它们可能会放在寄存器中。您的变量可能根本不存在,因为它们从未被使用过。

更新:如 cmets 中所述,C(但还不是 C++)允许动态大小的本地数组。显然,在知道大小之前无法分配这些空间。

【讨论】:

  • 一些编译器可能会在执行进入定义变量的范围或遇到定义时为变量分配空间。这意味着在 OP 的示例中,Y 和 Z 变量将在执行进入它们各自的语句块时分配,而不是在函数的开头。
  • 甚至因为分配没有效果。因此,根据编译器的不同,甚至函数本身也可能被完全删除。
  • @ThomasMatthews:确实,编译器可以做到这一点。但是,在大多数平台上,这会比单次分配效率低,因此通常不会。
  • @MikeSeymour:每个 C 1999 或 2011 实现都必须支持任意点的自动(类似堆栈)分配,而不仅仅是函数入口。考虑void foo(int x) { … int n = bar(x); char c[n]; … }。在进入foo 时,编译器无法为c 分配空间,因为所需的空间是未知的。一个实现应该只在函数的开头为对象进行分配,这些对象都具有可预先计算的大小,并且在每个可能的分支中都使用过或者很小。
  • @EricPostpischil:很公平;我在考虑 C++,其中没有动态大小的对象(至少,直到明年)。正如您所说,它们的分配必须推迟到知道大小为止。
【解决方案2】:
int foo(int input)
{ // BLOCK 1
    int x = 5;
    if( input == 0 )
    { // BLOCK 2
        int y = input * (x + 6);
        // other code here
    }
    else
    { // BLOCK 3
        int z = input + x;
        // other code here
    }
}

编译器可以优化大部分内容,但高级语言规则如下:

xBLOCK 1 和任何子块(BLOCK 2BLOCK 3)中有效。 y 仅在 BLOCK 2 中有效。 z 仅在 BLOCK 3 中有效。

编译器进行的第一次传递通常会保留这些规则。随后的传递通常会看到您没有使用变量(或优化它们的使用方式),并且可能会移动它们或根本不将它们存储在内存中(例如,它们可能只是放在寄存器中),因此尝试将它们等同起来高级语言的范围到如何在汇编中进行优化是徒劳的。

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多