何时在编译期间分配内存?

时间:2009-06-06 14:07:10

标签: c

写作时

int main()
{
    int j;
}

编译时分配'j'的内存,但是在编译期间?当内存分配给变量时,编译的各个阶段是什么?如果j是全局的怎么办?

8 个答案:

答案 0 :(得分:8)

我猜你是在混淆。

编译器不为变量分配内存 - 它生成在运行时为变量分配内存的代码。对于全局变量,将添加到程序启动代码中。

答案 1 :(得分:5)

在编译时,你的'int j'将在应用程序启动时分配,当应用程序进入main()范围时(实际上它不会在技术上得到分配,因为正在使用堆栈),全局变量将获得在进入main()范围之前在运行时分配。

答案 2 :(得分:5)

在C中,main的编译与其他每个函数的编译方式相同:在main中声明的任何变量都将在堆栈中“分配”。堆栈帧是单个函数调用使用的堆栈部分。该框架包含函数中使用的所有本地的插槽。此内存被认为是临时的,因为当函数返回时,此框架将从堆栈中弹出。

C编译器将为全局变量分配静态地址。该地址被认为是二进制文件“图像”的一部分,因此在内存中具有静态位置。 C编译器知道每种类型的大小,因此它可以为每个全局变量在二进制的内存布局中留出适当的空间量。然后,访问此变量的任何代码都将简单地引用此地址。

您可以使用以下代码检查变量的地址:

#include<stdio.h>

int i;

void foo(int n)
{
    if(n > 2)
        return;

    printf("From foo &n = %xd\n", &n);
    printf("From foo &i = %xd\n", &i);

    foo(n+1);
}


int main()
{
    printf("&i = %xd\n", &i);
    foo(0);
    return 0;
}

运行此代码会产生类似于:

的输出
./a.out 
&i = 600934d
From foo &n = 38bc4efcd
From foo &i = 600934d
From foo &n = 38bc4eccd
From foo &i = 600934d
From foo &n = 38bc4e9cd
From foo &i = 600934d

在这里你应该注意两件事:

  1. 每次引用时,i的地址都是常量
  2. n的地址(函数foo的局部变量)随着对foo的每次调用而变化。实际上,它会逐渐减少,因为堆栈向下增长。

答案 3 :(得分:2)

编译过程不分配内存。它生成分配内存的代码:)

在这种情况下, j 将是一个所谓的堆栈变量,它将在执行进入main()函数时分配。 全局变量和静态变量在堆上分配。

这是一个简短的解释:http://www.costech.or.tz/cs231/websites/C%20Programming/www-ee.eng.hawaii.edu/Courses/ee150/Book/chap14/subsection2.1.1.8.html。我会看看能不能找到更好的。

答案 4 :(得分:2)

编译生成程序的可执行代码。程序存储器在运行可执行代码时分配。

答案 5 :(得分:0)

由编译器决定放置j的位置。通常局部变量放在堆栈上,因此对于您的特定示例,编译器可能会在main函数的持续时间内保留堆栈上的空间。请注意,这与全局变量内存不同,后者可能会收到自己的内存。

答案 6 :(得分:0)

编译时未分配内存,但在运行时分配。 编译器只生成将执行程序的机器代码,实际分配在运行时发生。 在这种情况下,不使用变量,也不会为它发出任何代码。

答案 7 :(得分:0)

我认为你正在研究编译阶段,而不是'j'的内存分配。既然如此,那么就会发生这种情况:

一旦将源代码提供给C编译器,第一阶段就是词法和语义分析,其中分析语法和源代码的语义的正确性。如果发现错误,编译器会相应地报告并且不会继续。如果没有发现错误,则通常在各种优化之后继续生成源代码的中间表示。此中间表示可以是本机语言(OS /体系结构本机,如C语言)或独立于平台的字节码(如Python / Java ..)。编译器的功能在这里结束。

执行代码时,内存分配仅发生 。这是程序的运行时。这只是在编译阶段之后,你可能不想在这里知道。如果您愿意,请告诉我。我会尝试添加我知道的任何东西。

HTH。