为每个定义的整数保留一个四字节内存插槽。未初始化的变量保持该槽的旧值。因此,初始值以某种方式随机化。
int x = 5; // definition with initialisation
据我所知,在大多数 C++ 编译器中,这一事实适用于作用域变量。但是,当涉及到全局变量时。将设置为零值。
int x; // uninitialised definition
为什么 C++ 编译器在全局变量和作用域变量的初始值方面表现不同。
是基本的吗?
为每个定义的整数保留一个四字节内存插槽。未初始化的变量保持该槽的旧值。因此,初始值以某种方式随机化。
int x = 5; // definition with initialisation
据我所知,在大多数 C++ 编译器中,这一事实适用于作用域变量。但是,当涉及到全局变量时。将设置为零值。
int x; // uninitialised definition
为什么 C++ 编译器在全局变量和作用域变量的初始值方面表现不同。
是基本的吗?
命名空间级变量(即全局变量)属于静态存储时长,根据标准,所有具有静态存储时长的变量都是静态初始化的,这意味着所有位都设置为 0:
C++ 标准 (n3242) 的 §3.6.2/2 说,
具有静态存储持续时间(3.7.1) 或线程存储持续时间 (3.7.2)的变量应在任何其他初始化发生之前进行零初始化 (8.5)。
对于具有自动存储持续时间的局部变量,标准对编译器没有这样的要求。因此,出于性能原因,自动变量通常未初始化——几乎所有主要编译器都选择这种方法,尽管可能有一个编译器也会初始化自动变量。
“为每个定义的整数保留一个四字节内存插槽。” .
不,不是。忽略“4 字节”大小,该语句的主要问题是现代编译器通常在每次分配变量时都会为变量找到一个新位置。这可以是寄存器或内存中的某个位置。有很多聪明之处。
未初始化的变量不会被写入,因此通常甚至没有为其分配位置。尝试阅读“它”可能根本不会产生价值。编译器可能完全无法为此生成代码。
现在全局变量是另一回事。由于它们可以在任何地方读写,编译器不能在每次写入时为它们找到新的位置。他们必须坚持一个地方,而且它实际上不可能是一个寄存器。通常它们都一起分配在一块内存中。将该块归零通常可以非常有效地完成。这就是为什么全局变量不同的原因。
正如您所料,这种行为背后也有效率驱动的原因。
堆栈空间通常通过调整堆栈指针来“分配”。如果函数中有 32 个字节的简单变量,那么编译器会发出一条等效于“sp = sp - 32”的指令,这些变量的任何初始化都需要额外的代码和执行时间——因此它们最终会被初始化为明显的随机值。
全局变量完全是另一头野兽。简单变量由程序加载器有效分配,并且可以位于通常称为“BSS”的位置。这些变量在可执行文件中几乎不占用任何空间。所有这些都可以合并到一个块中——因此可执行映像只需要指定块的大小。由于操作系统必须确保新进程不会从某个现在已死的进程中看到内存中的任何剩余数据,因此内存需要填充一些东西——你也可以用零填充它。
初始化为非零的全局变量实际上确实占用了可执行文件中的空间,它们显示为数据块并且只是被加载到内存中 - 可执行文件中没有代码来初始化这些。
C++ 还允许需要执行代码才能初始化的全局变量,C 不允许这样做。例如“int x = rand();” 在运行时通过可执行文件中的代码进行初始化。
尝试添加这个全局变量 int x[1024 * 1024]; 看看它是否对可执行文件大小有影响。现在试试: int x[1024 * 1024] = {1,2,3}; 看看有什么不同。