书籍为什么说"编译器为内存中的变量分配空间"?

The*_*der 11 c++ compiler-construction runtime sizeof

书籍为什么说"编译器为内存中的变量分配空间".这不是可执行文件吗?我的意思是,例如,如果我写下面的程序,

#include <iostream>
using namespace std;

int main()
{
   int foo = 0;
   cout<<foo;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我运行program.exe,这个可执行文件将自己命令为变量foo分配一些空间,并编译它,并获得一个可执行文件(让它成为program.exe).不是吗?请解释为什么书籍继续说,"编译器会这样做......这样做"而实际上,编译后的可执行文件就是这样做的.

在这个问题中添加另一个相关问题,为什么sizeof称为编译时运算符?它不是一个实际的运行时运算符吗?

Suv*_*yil 20

当我们聘请建筑师设计房屋时,他或她会定义房间的大小等,并告知工人(劳动者).劳动者相应地做了工作.但我们仍然会说" 建筑师以这种方式建造房屋 ",而不是 " 劳动者以这种方式建造房屋 ".

劳动者只是执行建筑师定义的步骤.编译器实际上完成了在运行时检查和定义要分配多少内存的所有工作,然后只遵循这些指令.


Ton*_*ion 11

从技术上讲,创建空间本身的行为是在运行时完成的,但编译器是在你的情况下为你的变量确定在堆栈上保留多少空间的编译器foo.

编译器知道int类型的大小,因此可以生成正确的汇编程序指令,该指令将在堆栈上保留足够的空间以便让它foo存在.

如果您查看下面生成的汇编程序(使用MSVC2012)来显示您所显示的程序,我已经对其中的一些进行了评论,以向您展示会发生什么:

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
//Setup stack frame for main by storing the stack pointer from the calling function and 
//reserving space for local variables and storing commonly used registers on the stack
002E4390  push        ebp  
002E4391  mov         ebp,esp  
// reserve space for local variables, which is 204 bytes here, no idea why so much.
// this is where the compiler calculated the size of your foo and added that to whatever else needs to be stored on the stack. Subtract from stack pointer (esp) because stack grows downward.  
002E4393  sub         esp,0CCh  
002E4399  push        ebx  
002E439A  push        esi  
002E439B  push        edi  
002E439C  lea         edi,[ebp-0CCh]  // load effective address of [ebp-0CCh], which I suspect would be your foo variable into edi register
002E43A2  mov         ecx,33h  
002E43A7  mov         eax,0CCCCCCCCh  
002E43AC  rep stos    dword ptr es:[edi]  //fill block of memory at es:[edi] with stuff  
   int foo;
   return 0;
002E43AE  xor         eax,eax  //set eax to zero for return value
}
// restore everything back to how it was before main was called
    002E43B0  pop         edi  
    002E43B1  pop         esi  
    002E43B2  pop         ebx  
    002E43B3  mov         esp,ebp  
    002E43B5  pop         ebp  
    002E43B6  ret  
Run Code Online (Sandbox Code Playgroud)

  • @Abyx你错过了这一点.完全.我们的想法是向OP描述编译器如何生成描述给定程序的内存需求的程序集.不是具体的,也不是描述优化的可能性和方法. (3认同)
  • @JamesKanze我问了一个问题:http://stackoverflow.com/questions/15806673/why-is-so-much-space-allocated-on-the-stack因为我很好奇为什么会这样.我在里面提到过你 (2认同)

Luc*_*ore 7

这只是一个松散的术语使用.当然编译器不为程序分配内存.更准确的描述是它告诉运行时程序运行时要分配多少内存.

在程序实际运行之前,它不在内存中(除非它是动态加载的,但即使这种情况发生在运行时,因此超出了编译器的范围),因此没有内存可言.

这些书正在讨论的是分配大小在编译时已知的变量,而不是动态分配cin >> x; int * y = new[x];,其中大小未知.