18

可以准确地说在

void f() {
    int x;
    ...
}

int x;”表示在栈上分配sizeof(int)字节?

有什么规格吗?

4

5 回答 5

22

标准中没有任何内容要求存在堆栈。标准中没有任何内容要求局部变量需要为其分配内存。该变量可以放在寄存器中,甚至可以作为优化完全删除。

于 2013-09-17T07:24:35.800 回答
7

没有关于此的规范,您的假设通常(但不总是)是错误的。考虑一些代码,例如

void f() {
   int x;
   for (x=0; x<1000; x++) 
     { // do something with x 
     }
   // x is no more used here
}

首先,优化编译器将放入x机器的某个寄存器中,并且不消耗任何堆栈位置(除非您对地址执行某些操作,&x例如将其存储在全局中)。

编译器也可以展开该循环,并x从生成的代码中删除。例如,许多编译器会替换

for (x=0; x<5; x++) g(x);

相当于

g(0); g(1); g(2); g(3); g(4);

也许替换

for (x=0; x<10000; x++) t[x]=x;

有类似的东西

for (α = 0;  α < 10000;  α += 4) 
  { t[α] =  α; t[α+1] =  α+1; t[α+2] =  α+2; t[α+3] =  α+3; };

其中 α 是一个新变量(或者可能是x它本身)。

此外,可能没有堆栈。对于 C 来说,这是不常见的,但其他一些语言没有任何堆栈(例如,参见旧的 A.Appel 的书 compile with continuations)。

顺便说一句,如果使用GCC ,您可以使用例如MELT 探针(或使用gcc -fdump-tree-all它产生数百个转储文件!)来检查它的中间(Gimple)表示。

于 2013-09-17T07:23:51.797 回答
5

来自GNU

3.2.1 C 程序中的内存分配

当您声明一个自动变量(例如函数参数或局部变量)时,就会发生自动分配。自动变量的空间在输入包含声明的复合语句时分配,并在退出该复合语句时释放。在 GNU C 中,自动存储的大小可以是一个变化的表达式。在其他 C 实现中,它必须是常量。

于 2013-09-17T07:24:43.120 回答
1

这取决于很多因素。编译器可以优化并从堆栈中删除它,将值保留在寄存器中。等等

如果您在调试中编译,它肯定会在堆栈中分配一些空间,但您永远不知道。这没有具体说明。唯一指定的是变量的可见性以及它的大小和算术。查看C99 规范以获取更多信息。

于 2013-09-17T07:26:30.680 回答
0

我认为这取决于编译器。我为 Code::Blocks 和 Dev-C++ 使用了默认编译器,看起来内存是在初始化期间分配的。在以下 cout 语句中,将 n2 更改为 n1 将给出相同的答案。但是如果我将 n1 初始化为某个值,或者如果我在显示平均值之前显示 n2,我会得到一个不同的答案,它是垃圾。请注意,由于变量未初始化,VS 确实通过给出错误来正确处理此问题。

void getNums();
void getAverage();

int main()
{
    getNums();
    getAverage();

    return 0;
}
void getNums()
{
    int num1 = 4;
    double total = 10;
}
void getAverage()
{
    int counter;
    double n1 , n2;
    cout << n2/counter << endl;
}
于 2020-05-19T23:40:34.157 回答