C ++ Global和Scoped整数初始值

时间:2013-09-26 18:26:53

标签: c++ compiler-construction global-variables initialization

为每个定义的整数保留一个四字节内存插槽。未初始化的变量保持该槽的旧值。因此,初始值以某种方式随机化。

int x = 5; // definition with initialisation

就我所知,大多数C ++编译器中的这个事实都适用于范围变量。但是,当谈到全球变量时。将设置零值。

int x; // uninitialised definition

为什么C ++编译器在全局变量和范围变量的初始值方面表现不同。

这是根本吗?

3 个答案:

答案 0 :(得分:4)

命名空间级别变量(表示全局)属于静态存储持续时间,并且根据标准,所有具有静态存储持续时间的变量都是静态初始化的,这意味着所有位都设置为0:< / p> 来自C ++标准(n3242)的

§3.6.2/ 2说,

  

具有静态存储持续时间的变量(3.7.1)或线程存储持续时间(3.7.2)应在进行任何其他初始化之前进行零初始化(8.5)

如果本地变量具有自动存储持续时间,则标准会对编译器强加 no 此类要求。因此,出于性能原因,自动变量通常没有初始化 - 几乎所有主要编译器都选择这种方法,尽管可能还有一个编译器初始化自动变量。

答案 1 :(得分:2)

“为每个定义的整数保留一个四字节内存插槽。”

不,不是。忽略“4字节”大小,该语句的主要问题是现代编译器经常在每次分配变量时为变量找到新位置。这可以是寄存器或内存中的某个位置。这涉及很多聪明才智。

未写入未初始化的变量,因此通常甚至没有为其分配位置。试着读“它”可能根本不会产生价值;编译器可以彻底失败以生成代码。

现在全局变量是另一回事。由于它们可以从任何地方读取和写入,因此编译器不能在每次写入时为它们找到新的位置。他们必须坚持到一个地方,它实际上不能成为一个登记册。通常它们都被分配在一块内存中。通常可以非常有效地对该块进行归零。这就是全局变化的原因。

答案 2 :(得分:1)

正如您所料,这种行为背后也存在效率驱动的原因。

通常通过调整堆栈指针来“分配”堆栈空间。 如果函数中有32个字节的简单变量,则编译器会发出相当于“sp = sp - 32”的指令 这些变量的任何初始化都需要额外的代码和执行时间 - 因此它们最终被初始化为明显随机的值。

全局变量完全是另一种野兽。 简单变量由程序加载器有效分配,并且可以位于通常称为“BSS”的位置。这些变量在可执行文件中几乎不占用任何空间。所有这些都可以合并为一个块 - 因此可执行映像只需要指定块的大小。由于操作系统必须确保新进程无法从某些现在已经过时的进程中看到内存中的任何剩余数据,因此内存需要填充一些东西 - 您也可以用零填充它。

初始化为非零的全局变量实际上占用了可执行文件中的空间,它们显示为数据块并且只是加载到内存中 - 可执行文件中没有用于初始化这些的代码。

C ++还允许需要执行代码的全局变量进行初始化,C不允许这样做。 例如“int x = rand();” 通过可执行文件中的代码在运行时进行初始化。

尝试添加此全局变量    int x [1024 * 1024]; 并查看它是否对可执行文件大小有所影响。 现在尝试:    int x [1024 * 1024] = {1,2,3}; 看看它有什么不同。