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

时间:2021-09-07 06:57:04

When I write

当我写作

int main()
{
    int j;
}

The memory for 'j' is allotted at the time of compilation,but when during compilation ? What are the various stages of compilation when memory is allotted to a variable? What if j was global ?

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

8 个解决方案

#1


I guess you are mixing things up.

我猜你是在混淆。

Compiler doesn't allocate memory for variables - it generates code that allocates memory for variables at runtime. For globals is will be added to program start-up code.

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

#2


In C, main is compiled the same as every other function: any variables declared in main will be "allocated" on the stack. A stack frame is the portion of the stack that is used by a single function call. The frame contains slots for all of the locals used within a function. This memory is considered temporary since when the function returns, this frame will be popped off the stack.

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

The C compiler will assign a static address to global variables. This address is considered part of the binary's "image" and as such has a static location in memory. The C compiler knows the size of every type, so it can set aside the appropriate amount of space in the memory layout of the binary for each global variable. Then, any code that accesses this variable will simply reference this address instead.

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

You can examine a variable's address with code like this:

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

#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;
}

Running this code produces output similar to:

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

./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

There are two things you should notice here:

你应该注意两件事:

  1. The address of i is constant every time it is referenced
  2. 每次引用时,i的地址都是常量

  3. The address of n (a variable local to the function foo changes with each call to foo. In fact, it will decrease every time, since the stack grows downward.
  4. n的地址(函数foo的局部变量随着每次调用foo而变化。实际上,它会随着堆栈向下增长而每次都减少。

#3


Not at the time of compilation, your 'int j' will get allocated at application startup, when the application enter main() scope (actually it will not technically get allocated, as the stack is being used), globals will get allocated at runtime before entering main() scope.

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

#4


Compilation generates the executable code for a program. Program memory is allocated when that executable code is run.

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

#5


The compilation process doesn't allocate the memory. It generates the code that allocates the memory :)

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

In this case j would be a so-called stack variable and it would be allocated when execution enters the main() function. Global and static variables are allocated on the heap instead.

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

Here's a short explanation: http://www.costech.or.tz/cs231/websites/C%20Programming/www-ee.eng.hawaii.edu/Courses/ee150/Book/chap14/subsection2.1.1.8.html. I'll see if I can find a better one.

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

#6


It is up to the compiler where to place j. Usually local variables are placed on the stack and as such for your particular example, the compiler will probably reserve the space on the stack for the duration of the main function. Note that this is different from global variable memory, which may receive its own memory.

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

#7


The memory isn't allocated at the time of compilation, but at runtime. The compiler just generated machine code that will execute your program, actual allocations happen at runtime. In this case the variable isn't used and there won't emitted any code for it.

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

#8


I think you are looking at the stages of compilation, rather than the memory allocation of 'j'. Since I think so, here is what happens:

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

Once you feed your source code to the C compiler, the first stage(s) is(are) lexical and semantic analysis in which syntax and the semantics of the source code are analysed for correctness. If an error(s) was found, the compiler reports accordingly and does not go ahead. If no errors were found, it proceeds to the generation of a intermediate representation of the source code, usually after various optimisations. This intermediate representation can be in a native language (native to the OS/architecture, like in C) or a platform independent bytecode (like Python/Java..). The function of the compiler ends here.

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

Memory allocation happens only when you execute the code. This is the runtime of the program. This comes only after the compilation stage, which probably you wouldn't want to know here. If you want to, please let me know. I shall try and add whatever I know.

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

HTH.

#1


I guess you are mixing things up.

我猜你是在混淆。

Compiler doesn't allocate memory for variables - it generates code that allocates memory for variables at runtime. For globals is will be added to program start-up code.

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

#2


In C, main is compiled the same as every other function: any variables declared in main will be "allocated" on the stack. A stack frame is the portion of the stack that is used by a single function call. The frame contains slots for all of the locals used within a function. This memory is considered temporary since when the function returns, this frame will be popped off the stack.

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

The C compiler will assign a static address to global variables. This address is considered part of the binary's "image" and as such has a static location in memory. The C compiler knows the size of every type, so it can set aside the appropriate amount of space in the memory layout of the binary for each global variable. Then, any code that accesses this variable will simply reference this address instead.

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

You can examine a variable's address with code like this:

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

#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;
}

Running this code produces output similar to:

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

./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

There are two things you should notice here:

你应该注意两件事:

  1. The address of i is constant every time it is referenced
  2. 每次引用时,i的地址都是常量

  3. The address of n (a variable local to the function foo changes with each call to foo. In fact, it will decrease every time, since the stack grows downward.
  4. n的地址(函数foo的局部变量随着每次调用foo而变化。实际上,它会随着堆栈向下增长而每次都减少。

#3


Not at the time of compilation, your 'int j' will get allocated at application startup, when the application enter main() scope (actually it will not technically get allocated, as the stack is being used), globals will get allocated at runtime before entering main() scope.

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

#4


Compilation generates the executable code for a program. Program memory is allocated when that executable code is run.

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

#5


The compilation process doesn't allocate the memory. It generates the code that allocates the memory :)

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

In this case j would be a so-called stack variable and it would be allocated when execution enters the main() function. Global and static variables are allocated on the heap instead.

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

Here's a short explanation: http://www.costech.or.tz/cs231/websites/C%20Programming/www-ee.eng.hawaii.edu/Courses/ee150/Book/chap14/subsection2.1.1.8.html. I'll see if I can find a better one.

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

#6


It is up to the compiler where to place j. Usually local variables are placed on the stack and as such for your particular example, the compiler will probably reserve the space on the stack for the duration of the main function. Note that this is different from global variable memory, which may receive its own memory.

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

#7


The memory isn't allocated at the time of compilation, but at runtime. The compiler just generated machine code that will execute your program, actual allocations happen at runtime. In this case the variable isn't used and there won't emitted any code for it.

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

#8


I think you are looking at the stages of compilation, rather than the memory allocation of 'j'. Since I think so, here is what happens:

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

Once you feed your source code to the C compiler, the first stage(s) is(are) lexical and semantic analysis in which syntax and the semantics of the source code are analysed for correctness. If an error(s) was found, the compiler reports accordingly and does not go ahead. If no errors were found, it proceeds to the generation of a intermediate representation of the source code, usually after various optimisations. This intermediate representation can be in a native language (native to the OS/architecture, like in C) or a platform independent bytecode (like Python/Java..). The function of the compiler ends here.

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

Memory allocation happens only when you execute the code. This is the runtime of the program. This comes only after the compilation stage, which probably you wouldn't want to know here. If you want to, please let me know. I shall try and add whatever I know.

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

HTH.