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

当我写作

int main() { int j; } 

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

我猜你是在混淆。

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

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

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

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

 #include 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变化。实际上,它会随着堆栈向下增长而每次都减少。

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

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

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

在这种情况下, 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 。 我会看看能不能找到更好的一个。

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

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

我认为你正在研究编译阶段,而不是’j’的内存分配。 既然我这么认为,会发生以下情况:

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

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

HTH。